active_record_union 1.1.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0e5aaf90d66c3e15eb7e2c225283b0c2790b146b
4
- data.tar.gz: fb36ac1c86da58e19de86409e9bd3c35897e247f
3
+ metadata.gz: ae20ef21309b30f9193146326e3eaeace7cd5c51
4
+ data.tar.gz: a90fc0e536026c8d797624101090c8c91c8b9b73
5
5
  SHA512:
6
- metadata.gz: 3b0140dffec59d1214dc18c456dad0ff28c24f1262704ab7628af0f679dc08c5e30d9d8effcbff29fa4f6800894579b82f2663d15a1341b895512546f366c109
7
- data.tar.gz: 9683ecd6bd506d3226a04ddb3abcd461a7a3adb0088d0f577069569965bac460480bf35f5dd26fcf966779a24a0f1cb32cf531e5c8600dea86769ec540416c26
6
+ metadata.gz: 5559877947d4d9b10a37474235c2911de70c1273cc68a7bfadeea62f1f8f1477e131784752fa85bb6b9dca9cb056ff9ea059cad6477eed6316e9415731307074
7
+ data.tar.gz: 6c093a61bb9f60dc50129d0dce5a9ca83bf634471c1af8b9bba777ef1fdfb827eeddc436da14cddbaeca3720cebd1666261d48233fd063877a0dd191d1c35787
@@ -1,8 +1,8 @@
1
1
  language: ruby
2
2
  addons:
3
- postgresql: "9.3"
4
- before_script:
5
- - psql -c 'create database travis;' -U postgres # "travis" is the UNIX username, and therefore the default database name on connection
3
+ postgresql: "9.4"
6
4
  rvm:
7
- - 2.1.2
5
+ - 2.3.0
6
+ - 2.2.4
7
+ - 2.1.8
8
8
  - 2.0.0
data/README.md CHANGED
@@ -7,6 +7,16 @@ Use unions on ActiveRecord scopes without ugliness.
7
7
 
8
8
  If you find yourself writing `pluck(:id)` and then feeding that into another query, you may be able to reduce the number of database requests by using a nested query or a UNION without writing crazy JOIN statements.
9
9
 
10
+ Quick usage examples:
11
+
12
+ ```ruby
13
+ current_user.posts.union(Post.published)
14
+ current_user.posts.union(Post.published).where(id: [6, 7])
15
+ current_user.posts.union("published_at < ?", Time.now)
16
+ user_1.posts.union(user_2.posts).union(Post.published)
17
+ user_1.posts.union_all(user_2.posts)
18
+ ```
19
+
10
20
  ## Installation
11
21
 
12
22
  Add this line to your application's Gemfile:
@@ -174,6 +184,10 @@ This is a gem not a Rails pull request because the standard of code quality for
174
184
 
175
185
  ## Changelog
176
186
 
187
+ **1.1.1** - Mar 19, 2016
188
+ - Fix broken polymorphic associations and joins due to improper handling of bind values. Fix by [@efradelos](https://github.com/efradelos), reported by [@Machiaweliczny](https://github.com/Machiaweliczny).
189
+ - Quote table name aliases properly. Reported by [@odedniv](https://github.com/odedniv).
190
+
177
191
  **1.1.0** - Mar 29, 2015 - Add UNION ALL support, courtesy of [@pic](https://github.com/pic).
178
192
 
179
193
  **1.0.1** - Sept 2, 2014 - Allow ORDER BY in UNION subselects for databases that support it (not SQLite).
@@ -3,16 +3,16 @@ module ActiveRecord
3
3
  module Union
4
4
 
5
5
  SET_OPERATION_TO_AREL_CLASS = {
6
- "UNION" => Arel::Nodes::Union,
7
- "UNION ALL" => Arel::Nodes::UnionAll
6
+ union: Arel::Nodes::Union,
7
+ union_all: Arel::Nodes::UnionAll
8
8
  }
9
9
 
10
10
  def union(relation_or_where_arg, *args)
11
- set_operation("UNION", relation_or_where_arg, *args)
11
+ set_operation(:union, relation_or_where_arg, *args)
12
12
  end
13
13
 
14
14
  def union_all(relation_or_where_arg, *args)
15
- set_operation("UNION ALL", relation_or_where_arg, *args)
15
+ set_operation(:union_all, relation_or_where_arg, *args)
16
16
  end
17
17
 
18
18
  private
@@ -37,11 +37,11 @@ module ActiveRecord
37
37
  set = SET_OPERATION_TO_AREL_CLASS[operation].new(left, right)
38
38
  from = Arel::Nodes::TableAlias.new(
39
39
  set,
40
- Arel::Nodes::SqlLiteral.new(@klass.arel_table.name)
40
+ @klass.arel_table.name
41
41
  )
42
42
 
43
43
  relation = @klass.unscoped.from(from)
44
- relation.bind_values = self.bind_values + other.bind_values
44
+ relation.bind_values = self.arel.bind_values + self.bind_values + other.arel.bind_values + other.bind_values
45
45
  relation
46
46
  end
47
47
 
@@ -1,3 +1,3 @@
1
1
  module ActiveRecordUnion
2
- VERSION = "1.1.0"
2
+ VERSION = "1.1.1"
3
3
  end
@@ -35,12 +35,14 @@ module Databases
35
35
 
36
36
  def with_postgres(&block)
37
37
  connect_to_postgres
38
+ yield
38
39
  ensure
39
40
  connect_to_sqlite
40
41
  end
41
42
 
42
43
  def with_mysql(&block)
43
44
  connect_to_mysql
45
+ yield
44
46
  ensure
45
47
  connect_to_sqlite
46
48
  end
@@ -3,10 +3,12 @@ end
3
3
 
4
4
  class User < ActiveRecord::Base
5
5
  has_many :posts
6
+ has_many :drafts, -> { where draft: true }, class_name: "Post"
6
7
  end unless defined?(User)
7
8
 
8
9
  ActiveRecord::Base.connection.create_table :posts, force: true do |t|
9
10
  t.integer :user_id
11
+ t.boolean :draft
10
12
  t.timestamp :published_at
11
13
  t.timestamps null: false
12
14
  end
@@ -29,10 +29,10 @@ describe ActiveRecord::Relation do
29
29
  union = User.new(id: 1).posts.union(Post.where("created_at > ?", Time.utc(2014, 7, 19, 0, 0, 0)))
30
30
 
31
31
  expect(union.to_sql.squish).to eq(
32
- "SELECT \"posts\".* FROM ( SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = 1 UNION SELECT \"posts\".* FROM \"posts\" WHERE (created_at > '2014-07-19 00:00:00.000000') ) posts"
32
+ "SELECT \"posts\".* FROM ( SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = 1 UNION SELECT \"posts\".* FROM \"posts\" WHERE (created_at > '2014-07-19 00:00:00.000000') ) \"posts\""
33
33
  )
34
34
  expect(union.arel.to_sql.squish).to eq(
35
- "SELECT \"posts\".* FROM ( SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = ? UNION SELECT \"posts\".* FROM \"posts\" WHERE (created_at > '2014-07-19 00:00:00.000000') ) posts"
35
+ "SELECT \"posts\".* FROM ( SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = ? UNION SELECT \"posts\".* FROM \"posts\" WHERE (created_at > '2014-07-19 00:00:00.000000') ) \"posts\""
36
36
  )
37
37
  expect{union.to_a}.to_not raise_error
38
38
  end
@@ -43,11 +43,27 @@ describe ActiveRecord::Relation do
43
43
  user3 = User.new(id: 3)
44
44
 
45
45
  union = user1.posts.union(user2.posts).where.not(id: user3.posts)
46
- bind_values = union.bind_values.map { |column, value| value }
46
+
47
+ # Inside ActiveRecord the bind value list is
48
+ # (union.arel.bind_values + union.bind_values)
49
+ bind_values = (union.arel.bind_values + union.bind_values).map { |column, value| value }
47
50
 
48
51
  expect(bind_values).to eq([1, 2, 3])
49
52
  end
50
53
 
54
+ it "binds values properly on joins" do
55
+ union = User.joins(:drafts).union(User.where(id: 11))
56
+
57
+ bind_values = (union.arel.bind_values + union.bind_values).map { |column, value| value }
58
+ expect(bind_values).to eq([true, 11])
59
+
60
+
61
+ expect(union.to_sql.squish).to eq(
62
+ "SELECT \"users\".* FROM ( SELECT \"users\".* FROM \"users\" INNER JOIN \"posts\" ON \"posts\".\"user_id\" = \"users\".\"id\" AND \"posts\".\"draft\" = 't' UNION SELECT \"users\".* FROM \"users\" WHERE \"users\".\"id\" = 11 ) \"users\""
63
+ )
64
+ expect{union.to_a}.to_not raise_error
65
+ end
66
+
51
67
  it "doesn't repeat default scopes" do
52
68
  expect(Time).to receive(:now) { Time.utc(2014, 7, 24, 0, 0, 0) }
53
69
 
@@ -59,7 +75,7 @@ describe ActiveRecord::Relation do
59
75
  union = PublishedPost.where("created_at > ?", Time.utc(2014, 7, 19, 0, 0, 0)).union(User.new(id: 1).posts)
60
76
 
61
77
  expect(union.to_sql.squish).to eq(
62
- "SELECT \"posts\".* FROM ( SELECT \"posts\".* FROM \"posts\" WHERE (published_at < '2014-07-24 00:00:00.000000') AND (created_at > '2014-07-19 00:00:00.000000') UNION SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = 1 ) posts"
78
+ "SELECT \"posts\".* FROM ( SELECT \"posts\".* FROM \"posts\" WHERE (published_at < '2014-07-24 00:00:00.000000') AND (created_at > '2014-07-19 00:00:00.000000') UNION SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = 1 ) \"posts\""
63
79
  )
64
80
  expect{union.to_a}.to_not raise_error
65
81
  end
@@ -74,7 +90,7 @@ describe ActiveRecord::Relation do
74
90
  context "in SQLite" do
75
91
  it "lets ORDER BY in query subselects throw a syntax error" do
76
92
  expect(union.to_sql.squish).to eq(
77
- "SELECT \"posts\".* FROM ( SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = 1 ORDER BY \"posts\".\"created_at\" ASC UNION SELECT \"posts\".* FROM \"posts\" WHERE (created_at > '2014-07-19 00:00:00.000000') ORDER BY \"posts\".\"created_at\" ASC ) posts ORDER BY \"posts\".\"created_at\" ASC"
93
+ "SELECT \"posts\".* FROM ( SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = 1 ORDER BY \"posts\".\"created_at\" ASC UNION SELECT \"posts\".* FROM \"posts\" WHERE (created_at > '2014-07-19 00:00:00.000000') ORDER BY \"posts\".\"created_at\" ASC ) \"posts\" ORDER BY \"posts\".\"created_at\" ASC"
78
94
  )
79
95
  expect{union.to_a}.to raise_error(ActiveRecord::StatementInvalid)
80
96
  end
@@ -84,7 +100,7 @@ describe ActiveRecord::Relation do
84
100
  it "wraps query subselects in parentheses to allow ORDER BY clauses" do
85
101
  Databases.with_postgres do
86
102
  expect(union.to_sql.squish).to eq(
87
- "SELECT \"posts\".* FROM ( (SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = $1 ORDER BY \"posts\".\"created_at\" ASC) UNION (SELECT \"posts\".* FROM \"posts\" WHERE (created_at > '2014-07-19 00:00:00.000000') ORDER BY \"posts\".\"created_at\" ASC) ) posts ORDER BY \"posts\".\"created_at\" ASC"
103
+ "SELECT \"posts\".* FROM ( (SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = 1 ORDER BY \"posts\".\"created_at\" ASC) UNION (SELECT \"posts\".* FROM \"posts\" WHERE (created_at > '2014-07-19 00:00:00.000000') ORDER BY \"posts\".\"created_at\" ASC) ) \"posts\" ORDER BY \"posts\".\"created_at\" ASC"
88
104
  )
89
105
  expect{union.to_a}.to_not raise_error
90
106
  end
@@ -95,7 +111,7 @@ describe ActiveRecord::Relation do
95
111
  it "wraps query subselects in parentheses to allow ORDER BY clauses" do
96
112
  Databases.with_mysql do
97
113
  expect(union.to_sql.squish).to eq(
98
- "SELECT \"posts\".* FROM ( (SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = $1 ORDER BY \"posts\".\"created_at\" ASC) UNION (SELECT \"posts\".* FROM \"posts\" WHERE (created_at > '2014-07-19 00:00:00.000000') ORDER BY \"posts\".\"created_at\" ASC) ) posts ORDER BY \"posts\".\"created_at\" ASC"
114
+ "SELECT `posts`.* FROM ( (SELECT `posts`.* FROM `posts` WHERE `posts`.`user_id` = 1 ORDER BY `posts`.`created_at` ASC) UNION (SELECT `posts`.* FROM `posts` WHERE (created_at > '2014-07-19 00:00:00.000000') ORDER BY `posts`.`created_at` ASC) ) `posts` ORDER BY `posts`.`created_at` ASC"
99
115
  )
100
116
  expect{union.to_a}.to_not raise_error
101
117
  end
@@ -108,24 +124,27 @@ describe ActiveRecord::Relation do
108
124
  union = User.new(id: 1).posts.union(id: 2)
109
125
 
110
126
  expect(union.to_sql.squish).to eq(
111
- "SELECT \"posts\".* FROM ( SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = 1 UNION SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"id\" = 2 ) posts"
127
+ "SELECT \"posts\".* FROM ( SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = 1 UNION SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"id\" = 2 ) \"posts\""
112
128
  )
129
+ expect{union.to_a}.to_not raise_error
113
130
  end
114
131
 
115
132
  it "multiple arguments" do
116
133
  union = User.new(id: 1).posts.union("created_at > ?", Time.utc(2014, 7, 19, 0, 0, 0))
117
134
 
118
135
  expect(union.to_sql.squish).to eq(
119
- "SELECT \"posts\".* FROM ( SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = 1 UNION SELECT \"posts\".* FROM \"posts\" WHERE (created_at > '2014-07-19 00:00:00.000000') ) posts"
136
+ "SELECT \"posts\".* FROM ( SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = 1 UNION SELECT \"posts\".* FROM \"posts\" WHERE (created_at > '2014-07-19 00:00:00.000000') ) \"posts\""
120
137
  )
138
+ expect{union.to_a}.to_not raise_error
121
139
  end
122
140
 
123
141
  it "arel" do
124
142
  union = User.new(id: 1).posts.union(Post.arel_table[:id].eq(2).or(Post.arel_table[:id].eq(3)))
125
143
 
126
144
  expect(union.to_sql.squish).to eq(
127
- "SELECT \"posts\".* FROM ( SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = 1 UNION SELECT \"posts\".* FROM \"posts\" WHERE (\"posts\".\"id\" = 2 OR \"posts\".\"id\" = 3) ) posts"
145
+ "SELECT \"posts\".* FROM ( SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = 1 UNION SELECT \"posts\".* FROM \"posts\" WHERE (\"posts\".\"id\" = 2 OR \"posts\".\"id\" = 3) ) \"posts\""
128
146
  )
147
+ expect{union.to_a}.to_not raise_error
129
148
  end
130
149
  end
131
150
  end
@@ -135,7 +154,7 @@ describe ActiveRecord::Relation do
135
154
  union = User.new(id: 1).posts.union_all(Post.where("created_at > ?", Time.utc(2014, 7, 19, 0, 0, 0)))
136
155
 
137
156
  expect(union.to_sql.squish).to eq(
138
- "SELECT \"posts\".* FROM ( SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = 1 UNION ALL SELECT \"posts\".* FROM \"posts\" WHERE (created_at > '2014-07-19 00:00:00.000000') ) posts"
157
+ "SELECT \"posts\".* FROM ( SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"user_id\" = 1 UNION ALL SELECT \"posts\".* FROM \"posts\" WHERE (created_at > '2014-07-19 00:00:00.000000') ) \"posts\""
139
158
  )
140
159
  expect{union.to_a}.to_not raise_error
141
160
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_record_union
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Hempel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-30 00:00:00.000000000 Z
11
+ date: 2016-03-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -164,7 +164,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
164
164
  version: '0'
165
165
  requirements: []
166
166
  rubyforge_project:
167
- rubygems_version: 2.4.5
167
+ rubygems_version: 2.4.5.1
168
168
  signing_key:
169
169
  specification_version: 4
170
170
  summary: UNIONs in ActiveRecord! Adds proper union and union_all methods to ActiveRecord::Relation.