active_record_union 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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.