activerecord_any_of 1.2 → 1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -38
- data/Rakefile +9 -27
- data/lib/activerecord_any_of/alternative_builder.rb +25 -9
- data/lib/activerecord_any_of/version.rb +1 -1
- data/lib/activerecord_any_of.rb +4 -4
- data/spec/activerecord_any_of_spec.rb +196 -0
- data/spec/db/database.yml +28 -0
- data/spec/db/schema.rb +33 -0
- data/{test → spec}/fixtures/authors.yml +0 -0
- data/{test → spec}/fixtures/posts.yml +0 -0
- data/spec/fixtures/users.yml +9 -0
- data/spec/spec_helper.rb +36 -0
- data/spec/support/models.rb +34 -0
- metadata +76 -203
- data/test/activerecord_any_of_test.rb +0 -114
- data/test/dummy_rails3/README.rdoc +0 -261
- data/test/dummy_rails3/Rakefile +0 -7
- data/test/dummy_rails3/app/assets/javascripts/application.js +0 -15
- data/test/dummy_rails3/app/assets/stylesheets/application.css +0 -13
- data/test/dummy_rails3/app/controllers/application_controller.rb +0 -3
- data/test/dummy_rails3/app/helpers/application_helper.rb +0 -2
- data/test/dummy_rails3/app/models/author.rb +0 -4
- data/test/dummy_rails3/app/models/post.rb +0 -4
- data/test/dummy_rails3/app/models/special_post.rb +0 -2
- data/test/dummy_rails3/app/models/sti_post.rb +0 -2
- data/test/dummy_rails3/app/views/layouts/application.html.erb +0 -14
- data/test/dummy_rails3/config/application.rb +0 -59
- data/test/dummy_rails3/config/boot.rb +0 -10
- data/test/dummy_rails3/config/database.yml +0 -25
- data/test/dummy_rails3/config/environment.rb +0 -5
- data/test/dummy_rails3/config/environments/development.rb +0 -37
- data/test/dummy_rails3/config/environments/production.rb +0 -67
- data/test/dummy_rails3/config/environments/test.rb +0 -37
- data/test/dummy_rails3/config/initializers/backtrace_silencers.rb +0 -7
- data/test/dummy_rails3/config/initializers/inflections.rb +0 -15
- data/test/dummy_rails3/config/initializers/mime_types.rb +0 -5
- data/test/dummy_rails3/config/initializers/secret_token.rb +0 -7
- data/test/dummy_rails3/config/initializers/session_store.rb +0 -8
- data/test/dummy_rails3/config/initializers/wrap_parameters.rb +0 -14
- data/test/dummy_rails3/config/locales/en.yml +0 -5
- data/test/dummy_rails3/config/routes.rb +0 -58
- data/test/dummy_rails3/config.ru +0 -4
- data/test/dummy_rails3/db/development.sqlite3 +0 -0
- data/test/dummy_rails3/db/migrate/20130617172335_create_authors.rb +0 -9
- data/test/dummy_rails3/db/migrate/20130617173313_create_posts.rb +0 -12
- data/test/dummy_rails3/db/schema.rb +0 -31
- data/test/dummy_rails3/db/test.sqlite3 +0 -0
- data/test/dummy_rails3/log/development.log +0 -101
- data/test/dummy_rails3/log/test.log +0 -2875
- data/test/dummy_rails3/public/404.html +0 -26
- data/test/dummy_rails3/public/422.html +0 -26
- data/test/dummy_rails3/public/500.html +0 -25
- data/test/dummy_rails3/public/favicon.ico +0 -0
- data/test/dummy_rails3/script/rails +0 -6
- data/test/dummy_rails3/test/fixtures/authors.yml +0 -7
- data/test/dummy_rails3/test/fixtures/posts.yml +0 -13
- data/test/dummy_rails3/test/unit/author_test.rb +0 -7
- data/test/dummy_rails3/test/unit/post_test.rb +0 -7
- data/test/dummy_rails4/README.rdoc +0 -28
- data/test/dummy_rails4/Rakefile +0 -6
- data/test/dummy_rails4/app/assets/javascripts/application.js +0 -13
- data/test/dummy_rails4/app/assets/stylesheets/application.css +0 -13
- data/test/dummy_rails4/app/controllers/application_controller.rb +0 -5
- data/test/dummy_rails4/app/helpers/application_helper.rb +0 -2
- data/test/dummy_rails4/app/models/author.rb +0 -3
- data/test/dummy_rails4/app/models/post.rb +0 -3
- data/test/dummy_rails4/app/models/special_post.rb +0 -2
- data/test/dummy_rails4/app/models/sti_post.rb +0 -2
- data/test/dummy_rails4/app/views/layouts/application.html.erb +0 -14
- data/test/dummy_rails4/bin/bundle +0 -3
- data/test/dummy_rails4/bin/rails +0 -4
- data/test/dummy_rails4/bin/rake +0 -4
- data/test/dummy_rails4/config/application.rb +0 -23
- data/test/dummy_rails4/config/boot.rb +0 -5
- data/test/dummy_rails4/config/database.yml +0 -25
- data/test/dummy_rails4/config/environment.rb +0 -5
- data/test/dummy_rails4/config/environments/development.rb +0 -29
- data/test/dummy_rails4/config/environments/production.rb +0 -80
- data/test/dummy_rails4/config/environments/test.rb +0 -36
- data/test/dummy_rails4/config/initializers/backtrace_silencers.rb +0 -7
- data/test/dummy_rails4/config/initializers/filter_parameter_logging.rb +0 -4
- data/test/dummy_rails4/config/initializers/inflections.rb +0 -16
- data/test/dummy_rails4/config/initializers/mime_types.rb +0 -5
- data/test/dummy_rails4/config/initializers/secret_token.rb +0 -12
- data/test/dummy_rails4/config/initializers/session_store.rb +0 -3
- data/test/dummy_rails4/config/initializers/wrap_parameters.rb +0 -14
- data/test/dummy_rails4/config/locales/en.yml +0 -23
- data/test/dummy_rails4/config/routes.rb +0 -56
- data/test/dummy_rails4/config.ru +0 -4
- data/test/dummy_rails4/db/development.sqlite3 +0 -0
- data/test/dummy_rails4/db/migrate/20130617172335_create_authors.rb +0 -9
- data/test/dummy_rails4/db/migrate/20130617173313_create_posts.rb +0 -12
- data/test/dummy_rails4/db/schema.rb +0 -31
- data/test/dummy_rails4/db/test.sqlite3 +0 -0
- data/test/dummy_rails4/log/development.log +0 -21
- data/test/dummy_rails4/log/test.log +0 -1527
- data/test/dummy_rails4/public/404.html +0 -58
- data/test/dummy_rails4/public/422.html +0 -58
- data/test/dummy_rails4/public/500.html +0 -57
- data/test/dummy_rails4/public/favicon.ico +0 -0
- data/test/dummy_rails4/test/fixtures/authors.yml +0 -7
- data/test/dummy_rails4/test/fixtures/posts.yml +0 -13
- data/test/dummy_rails4/test/unit/author_test.rb +0 -7
- data/test/dummy_rails4/test/unit/post_test.rb +0 -7
- data/test/test_helper.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3086cee8dc2889c8e3f8874ef32631af08c750c2
|
4
|
+
data.tar.gz: 5e01aa2499c952e4fc215c24890b215d1749f104
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2288d0dec57e66b4b9b454f6082eca83125d30912044de57aedfc828f8aa20b98137b0d71c7de5b53a81f94a9c2f3ec6b2b6373b7afa1f10be58e1c127013832
|
7
|
+
data.tar.gz: 59c3984d1052c8cff9b04cf5bd8bd07b19fef3e3082d7379f56383a6531bf63bf94b002c810c24aa56d899948b14f923313f06a2c41fd78697dbd11632a36c8b
|
data/README.md
CHANGED
@@ -17,7 +17,7 @@ expected result, this should have been used :
|
|
17
17
|
User.where.any_of({name: 'Doe'}, {active: true})
|
18
18
|
```
|
19
19
|
|
20
|
-
|
20
|
+
|
21
21
|
To be true to principle of least surprise, we now automatically expand
|
22
22
|
parameters consisting of a single Hash as a hash for each key, so first
|
23
23
|
query will indeed generate :
|
@@ -156,51 +156,18 @@ OR offline = '1'` ? Or `where email LIKE '%@example.com' AND ( active = '1' OR
|
|
156
156
|
offline = '1' )` ? This can quickly get messy and counter intuitive.
|
157
157
|
|
158
158
|
The MongoId solution is quite elegant. Using `#any_of`, it is made clear which
|
159
|
-
conditions are grouped through `OR` and which are grouped through `AND` :
|
160
|
-
|
161
|
-
* `User.where( "email LIKE '%@example.com" ).any_of({ active: true }, { offline: true })`
|
162
|
-
* `fakes = User.where( "email LIKE '%@example.com'" ).where( active: true ); User.any_of( fakes, { offline: true })`
|
159
|
+
conditions are grouped through `OR` and which are grouped through `AND` :
|
163
160
|
|
161
|
+
* `User.where( "email LIKE '%@example.com" ).where.any_of({ active: true }, { offline: true })`
|
162
|
+
* `fakes = User.where( "email LIKE '%@example.com'" ).where( active: true ); User.where.any_of( fakes, { offline: true })`
|
164
163
|
|
165
164
|
## I want this in active_record
|
166
165
|
|
167
166
|
You can [say it there](https://github.com/rails/rails/pull/10891).
|
168
167
|
|
169
|
-
|
170
168
|
## Running test
|
171
169
|
|
172
|
-
|
173
|
-
have to run them seperately, but it's ok to use the same directory / machine to
|
174
|
-
run both.
|
175
|
-
|
176
|
-
### Running tests with rails-4
|
177
|
-
|
178
|
-
```shell
|
179
|
-
# One time setup
|
180
|
-
bundle install --gemfile Gemfile.rails4
|
181
|
-
cd test/dummy_rails4
|
182
|
-
BUNDLE_GEMFILE=../../Gemfile.rails4 bundle exec rake db:migrate
|
183
|
-
BUNDLE_GEMFILE=../../Gemfile.rails4 bundle exec rake db:test:prepare
|
184
|
-
cd ../..
|
185
|
-
|
186
|
-
# Then
|
187
|
-
bundle exec rake test
|
188
|
-
```
|
189
|
-
|
190
|
-
### Running tests with rails-3
|
191
|
-
|
192
|
-
```shell
|
193
|
-
# One time setup
|
194
|
-
bundle install --gemfile Gemfile.rails3
|
195
|
-
cd test/dummy_rails3
|
196
|
-
BUNDLE_GEMFILE=../../Gemfile.rails3 bundle exec rake db:migrate
|
197
|
-
BUNDLE_GEMFILE=../../Gemfile.rails3 bundle exec rake db:test:prepare
|
198
|
-
cd ../..
|
199
|
-
|
200
|
-
# Then
|
201
|
-
RAILS_VERSION=3 bundle exec rake test
|
202
|
-
```
|
203
|
-
|
170
|
+
Testing is done using TravisCI. You can use the wonderful [wwtd gem](https://github.com/grosser/wwtd) to run all tests locally. By default, the task to run is `bundle exec rake spec`, and will run against `sqlite3` in memory. You can change the database like so: `DB=postgresql bundle exec rake spec`. Please note that you may need to change the credentials for your database in the `database.yml` file. *Do not commit those changes.*
|
204
171
|
|
205
172
|
## Pull requests
|
206
173
|
|
data/Rakefile
CHANGED
@@ -1,18 +1,17 @@
|
|
1
1
|
#!/usr/bin/env rake
|
2
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
|
2
3
|
|
3
|
-
|
4
|
+
require 'rubygems'
|
5
|
+
require 'bundler/setup'
|
6
|
+
require 'activerecord_any_of/version'
|
4
7
|
|
5
|
-
|
6
|
-
ENV[ 'BUNDLE_GEMFILE' ] = 'Gemfile.rails3'
|
7
|
-
else
|
8
|
-
ENV[ 'BUNDLE_GEMFILE' ] = 'Gemfile.rails4'
|
9
|
-
end
|
8
|
+
task :default => :spec
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
10
|
+
task :spec do
|
11
|
+
puts "\n" + (cmd = "bundle exec rspec spec")
|
12
|
+
system cmd
|
15
13
|
end
|
14
|
+
|
16
15
|
begin
|
17
16
|
require 'rdoc/task'
|
18
17
|
rescue LoadError
|
@@ -28,20 +27,3 @@ RDoc::Task.new(:rdoc) do |rdoc|
|
|
28
27
|
rdoc.rdoc_files.include('README.rdoc')
|
29
28
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
30
29
|
end
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
Bundler::GemHelper.install_tasks
|
36
|
-
|
37
|
-
require 'rake/testtask'
|
38
|
-
|
39
|
-
Rake::TestTask.new(:test) do |t|
|
40
|
-
t.libs << 'lib'
|
41
|
-
t.libs << 'test'
|
42
|
-
t.pattern = 'test/**/*_test.rb'
|
43
|
-
t.verbose = false
|
44
|
-
end
|
45
|
-
|
46
|
-
|
47
|
-
task :default => :test
|
@@ -37,13 +37,23 @@ module ActiverecordAnyOf
|
|
37
37
|
self.queries_bind_values += query.bind_values if query.bind_values.any?
|
38
38
|
queries_joins_values[:includes].concat(query.includes_values) if query.includes_values.any?
|
39
39
|
queries_joins_values[:joins].concat(query.joins_values) if query.joins_values.any?
|
40
|
-
queries_joins_values[:references].concat(query.references_values) if
|
40
|
+
queries_joins_values[:references].concat(query.references_values) if ActiveRecord::VERSION::MAJOR >= 4 && query.references_values.any?
|
41
41
|
query.arel.constraints.reduce(:and)
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
45
|
def uniq_queries_joins_values
|
46
|
-
@uniq_queries_joins_values ||=
|
46
|
+
@uniq_queries_joins_values ||= begin
|
47
|
+
{ includes: [], joins: [], references: [] }.tap do |values|
|
48
|
+
queries_joins_values.each do |join_type, statements|
|
49
|
+
if Symbol === statements.first or String === statements.first
|
50
|
+
values[ join_type ] = statements.uniq
|
51
|
+
else
|
52
|
+
values[ join_type ] = statements.uniq( &:to_sql )
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
47
57
|
end
|
48
58
|
|
49
59
|
def method_missing(method_name, *args, &block)
|
@@ -51,7 +61,7 @@ module ActiverecordAnyOf
|
|
51
61
|
end
|
52
62
|
|
53
63
|
def add_joins_to(relation)
|
54
|
-
relation = relation.references(uniq_queries_joins_values[:references]) if
|
64
|
+
relation = relation.references(uniq_queries_joins_values[:references]) if ActiveRecord::VERSION::MAJOR >= 4
|
55
65
|
relation = relation.includes(uniq_queries_joins_values[:includes])
|
56
66
|
relation.joins(uniq_queries_joins_values[:joins])
|
57
67
|
end
|
@@ -60,10 +70,16 @@ module ActiverecordAnyOf
|
|
60
70
|
relation.bind_values += queries_bind_values
|
61
71
|
relation.includes_values += uniq_queries_joins_values[:includes]
|
62
72
|
relation.joins_values += uniq_queries_joins_values[:joins]
|
63
|
-
relation.references_values += uniq_queries_joins_values[:references] if
|
73
|
+
relation.references_values += uniq_queries_joins_values[:references] if ActiveRecord::VERSION::MAJOR >= 4
|
64
74
|
|
65
75
|
relation
|
66
76
|
end
|
77
|
+
|
78
|
+
def unprepare_query(query)
|
79
|
+
query.gsub(/((?<!\\)'.*?(?<!\\)'|(?<!\\)".*?(?<!\\)")|(\=\ \$\d)/) do |match|
|
80
|
+
$2 and $2.gsub(/\=\ \$\d/, "= ?") or match
|
81
|
+
end
|
82
|
+
end
|
67
83
|
end
|
68
84
|
|
69
85
|
class PositiveBuilder < Builder
|
@@ -71,7 +87,7 @@ module ActiverecordAnyOf
|
|
71
87
|
|
72
88
|
def with_statement_cache
|
73
89
|
if queries && queries_bind_values.any?
|
74
|
-
relation = where([queries.reduce(:or).to_sql, *queries_bind_values.map { |v| v[1] }])
|
90
|
+
relation = where([unprepare_query(queries.reduce(:or).to_sql), *queries_bind_values.map { |v| v[1] }])
|
75
91
|
else
|
76
92
|
relation = where(queries.reduce(:or).to_sql)
|
77
93
|
end
|
@@ -89,15 +105,15 @@ module ActiverecordAnyOf
|
|
89
105
|
private
|
90
106
|
|
91
107
|
def with_statement_cache
|
92
|
-
if
|
108
|
+
if ActiveRecord::VERSION::MAJOR >= 4
|
93
109
|
if queries && queries_bind_values.any?
|
94
|
-
relation = where.not([queries.reduce(:or).to_sql, *queries_bind_values.map { |v| v[1] }])
|
110
|
+
relation = where.not([unprepare_query(queries.reduce(:or).to_sql), *queries_bind_values.map { |v| v[1] }])
|
95
111
|
else
|
96
112
|
relation = where.not(queries.reduce(:or).to_sql)
|
97
113
|
end
|
98
114
|
else
|
99
115
|
if queries && queries_bind_values.any?
|
100
|
-
relation = where([Arel::Nodes::Not.new(queries.reduce(:or)).to_sql, *queries_bind_values.map { |v| v[1] }])
|
116
|
+
relation = where([unprepare_query(Arel::Nodes::Not.new(queries.reduce(:or)).to_sql), *queries_bind_values.map { |v| v[1] }])
|
101
117
|
else
|
102
118
|
relation = where(Arel::Nodes::Not.new(queries.reduce(:or)).to_sql)
|
103
119
|
end
|
@@ -107,7 +123,7 @@ module ActiverecordAnyOf
|
|
107
123
|
end
|
108
124
|
|
109
125
|
def without_statement_cache
|
110
|
-
if
|
126
|
+
if ActiveRecord::VERSION::MAJOR >= 4
|
111
127
|
relation = where.not(queries.reduce(:or))
|
112
128
|
else
|
113
129
|
relation = where(Arel::Nodes::Not.new(queries.reduce(:or)))
|
data/lib/activerecord_any_of.rb
CHANGED
@@ -57,7 +57,7 @@ module ActiverecordAnyOf
|
|
57
57
|
|
58
58
|
module Deprecated
|
59
59
|
def any_of(*queries)
|
60
|
-
if
|
60
|
+
if ActiveRecord::VERSION::MAJOR >= 4
|
61
61
|
ActiveSupport::Deprecation.warn( "Calling #any_of directly is deprecated and will be removed in activerecord_any_of-1.2.\nPlease call it with #where : User.where.any_of(cond1, cond2)." )
|
62
62
|
end
|
63
63
|
|
@@ -66,7 +66,7 @@ module ActiverecordAnyOf
|
|
66
66
|
end
|
67
67
|
|
68
68
|
def none_of(*queries)
|
69
|
-
if
|
69
|
+
if ActiveRecord::VERSION::MAJOR >= 4
|
70
70
|
ActiveSupport::Deprecation.warn( "Calling #none_of directly is deprecated and will be removed in activerecord_any_of-1.2.\nPlease call it with #where : User.where.none_of(cond1, cond2)." )
|
71
71
|
end
|
72
72
|
|
@@ -76,7 +76,7 @@ module ActiverecordAnyOf
|
|
76
76
|
end
|
77
77
|
end
|
78
78
|
|
79
|
-
if
|
79
|
+
if ActiveRecord::VERSION::MAJOR >= 4
|
80
80
|
module ActiverecordAnyOfDelegation
|
81
81
|
delegate :any_of, to: :all
|
82
82
|
delegate :none_of, to: :all
|
@@ -89,5 +89,5 @@ else
|
|
89
89
|
end
|
90
90
|
|
91
91
|
ActiveRecord::Relation.send(:include, ActiverecordAnyOf::Deprecated)
|
92
|
-
ActiveRecord::Relation::WhereChain.send(:include, ActiverecordAnyOf::Chained) if
|
92
|
+
ActiveRecord::Relation::WhereChain.send(:include, ActiverecordAnyOf::Chained) if ActiveRecord::VERSION::MAJOR >= 4
|
93
93
|
ActiveRecord::Base.send(:extend, ActiverecordAnyOfDelegation)
|
@@ -0,0 +1,196 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ActiverecordAnyOf do
|
4
|
+
fixtures :authors, :posts, :users
|
5
|
+
|
6
|
+
describe 'finding with alternate conditions' do
|
7
|
+
let(:davids) { Author.where(name: "David") }
|
8
|
+
|
9
|
+
it "matches hash combinations" do
|
10
|
+
if ActiveRecord::VERSION::MAJOR >= 4
|
11
|
+
expect(Author.where.any_of({name: 'David'}, {name: 'Mary'})).to match_array(authors(:david, :mary))
|
12
|
+
else
|
13
|
+
expect(Author.any_of({name: 'David'}, {name: 'Mary'})).to match_array(authors(:david, :mary))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it "matches combination of hash and array" do
|
18
|
+
if ActiveRecord::VERSION::MAJOR >= 4
|
19
|
+
expect(Author.where.any_of({name: 'David'}, ['name = ?', 'Mary'])).to match_array(authors(:david, :mary))
|
20
|
+
else
|
21
|
+
expect(Author.any_of({name: 'David'}, ['name = ?', 'Mary'])).to match_array(authors(:david, :mary))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it "matches a combination of hashes, arrays, and AR relations" do
|
26
|
+
if ActiveRecord::VERSION::MAJOR >= 4
|
27
|
+
expect(Author.where.any_of(davids, ['name = ?', 'Mary'], {name: 'Bob'})).to match_array(authors(:david, :mary, :bob))
|
28
|
+
else
|
29
|
+
expect(Author.any_of(davids, ['name = ?', 'Mary'], {name: 'Bob'})).to match_array(authors(:david, :mary, :bob))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
it "matches a combination of strings, hashes, and AR relations" do
|
34
|
+
if ActiveRecord::VERSION::MAJOR >= 4
|
35
|
+
expect(Author.where.any_of(davids, "name = 'Mary'", {name: 'Bob', id: 3})).to match_array(authors(:david, :mary, :bob))
|
36
|
+
else
|
37
|
+
expect(Author.any_of(davids, "name = 'Mary'", {name: 'Bob', id: 3})).to match_array(authors(:david, :mary, :bob))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it "doesn't find combinations previously filtered out" do
|
42
|
+
if ActiveRecord::VERSION::MAJOR >= 4
|
43
|
+
expect(Author.where.not(name: 'Mary').where.any_of(davids, ['name = ?', 'Mary'])).to match_array([authors(:david)])
|
44
|
+
else
|
45
|
+
expect(Author.where("name != 'Mary'").any_of(davids, ['name = ?', 'Mary'])).to match_array([authors(:david)])
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'finding with alternate conditions on has_many association' do
|
51
|
+
david = authors(:david)
|
52
|
+
welcome = david.posts.where(body: 'Such a lovely day')
|
53
|
+
expected = ['Welcome to the weblog', 'So I was thinking']
|
54
|
+
|
55
|
+
if ActiveRecord::VERSION::MAJOR >= 4
|
56
|
+
expect(david.posts.where.any_of(welcome, {type: 'SpecialPost'}).map(&:title)).to match_array(expected)
|
57
|
+
else
|
58
|
+
expect(david.posts.any_of(welcome, {type: 'SpecialPost'}).map(&:title)).to match_array(expected)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'finds with combined polymorphic associations' do
|
63
|
+
company = Company.create!
|
64
|
+
university = University.create!
|
65
|
+
|
66
|
+
company.users << users(:ezra)
|
67
|
+
university.users << users(:aria)
|
68
|
+
|
69
|
+
if ActiveRecord::VERSION::MAJOR >= 4
|
70
|
+
expect(User.where.any_of(company.users, university.users)).to match_array(users(:ezra, :aria))
|
71
|
+
else
|
72
|
+
expect(User.any_of(company.users, university.users)).to match_array(users(:ezra, :aria))
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'finds with more than 2 combined polymorphic associations' do
|
77
|
+
company = Company.create!
|
78
|
+
university = University.create!
|
79
|
+
company2 = Company.create!
|
80
|
+
|
81
|
+
company.users << users(:ezra)
|
82
|
+
university.users << users(:aria)
|
83
|
+
company2.users << users(:james)
|
84
|
+
|
85
|
+
if ActiveRecord::VERSION::MAJOR >= 4
|
86
|
+
expect(User.where.any_of(company.users, university.users, company2.users)).to match_array(users(:ezra, :aria, :james))
|
87
|
+
else
|
88
|
+
expect(User.any_of(company.users, university.users, company2.users)).to match_array(users(:ezra, :aria, :james))
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'finds alternatives with combined has_many associations' do
|
93
|
+
david, mary = authors(:david, :mary)
|
94
|
+
|
95
|
+
if ActiveRecord::VERSION::MAJOR >= 4
|
96
|
+
expect(Post.where.any_of(david.posts, mary.posts)).to match_array(david.posts + mary.posts)
|
97
|
+
else
|
98
|
+
expect(Post.any_of(david.posts, mary.posts)).to match_array(david.posts + mary.posts)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'finds alternatives with more than 2 combined has_many associations' do
|
103
|
+
david, mary, bob = authors(:david, :mary, :bob)
|
104
|
+
|
105
|
+
if ActiveRecord::VERSION::MAJOR >= 4
|
106
|
+
expect(Post.where.any_of(david.posts, mary.posts, bob.posts)).to match_array(david.posts + mary.posts + bob.posts)
|
107
|
+
else
|
108
|
+
expect(Post.any_of(david.posts, mary.posts, bob.posts)).to match_array(david.posts + mary.posts + bob.posts)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe 'finding alternate dynamically with joined queries' do
|
113
|
+
it "matches combined AR relations with joins" do
|
114
|
+
david = Author.where(posts: { title: 'Welcome to the weblog' }).joins(:posts)
|
115
|
+
mary = Author.where(posts: { title: "eager loading with OR'd conditions" }).joins(:posts)
|
116
|
+
|
117
|
+
if ActiveRecord::VERSION::MAJOR >= 4
|
118
|
+
expect(Author.where.any_of(david, mary)).to match_array(authors(:david, :mary))
|
119
|
+
else
|
120
|
+
expect(Author.any_of(david, mary)).to match_array(authors(:david, :mary))
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
it "matches combined AR relations with joins and includes" do
|
125
|
+
if ActiveRecord::VERSION::MAJOR >= 4
|
126
|
+
david = Author.where(posts: { title: 'Welcome to the weblog' }).includes(:posts).references(:posts)
|
127
|
+
mary = Author.where(posts: { title: "eager loading with OR'd conditions" }).includes(:posts).references(:posts)
|
128
|
+
expect(Author.where.any_of(david, mary)).to match_array(authors(:david, :mary))
|
129
|
+
else
|
130
|
+
david = Author.where(posts: { title: 'Welcome to the weblog' }).includes(:posts)
|
131
|
+
mary = Author.where(posts: { title: "eager loading with OR'd conditions" }).includes(:posts)
|
132
|
+
expect(Author.any_of(david, mary)).to match_array(authors(:david, :mary))
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'finding with alternate negative conditions' do
|
138
|
+
if ActiveRecord::VERSION::MAJOR >= 4
|
139
|
+
expect(Author.where.none_of({name: 'David'}, {name: 'Mary'})).to match_array([authors(:bob)])
|
140
|
+
else
|
141
|
+
expect(Author.none_of({name: 'David'}, {name: 'Mary'})).to match_array([authors(:bob)])
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'finding with alternate negative conditions on association' do
|
146
|
+
david = Author.where(name: 'David').first
|
147
|
+
welcome = david.posts.where(body: 'Such a lovely day')
|
148
|
+
expected = ['sti comments', 'sti me', 'habtm sti test']
|
149
|
+
|
150
|
+
if ActiveRecord::VERSION::MAJOR >= 4
|
151
|
+
expect(david.posts.where.none_of(welcome, {type: 'SpecialPost'}).map(&:title)).to match_array(expected)
|
152
|
+
else
|
153
|
+
expect(david.posts.none_of(welcome, {type: 'SpecialPost'}).map(&:title)).to match_array(expected)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'calling #any_of with no argument raise exception' do
|
158
|
+
if ActiveRecord::VERSION::MAJOR >= 4
|
159
|
+
expect { Author.where.any_of }.to raise_exception(ArgumentError)
|
160
|
+
else
|
161
|
+
expect { Author.any_of }.to raise_exception(ArgumentError)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
it 'calling #none_of with no argument raise exception' do
|
166
|
+
if ActiveRecord::VERSION::MAJOR >= 4
|
167
|
+
expect { Author.where.none_of }.to raise_exception(ArgumentError)
|
168
|
+
else
|
169
|
+
expect { Author.none_of }.to raise_exception(ArgumentError)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'calling #any_of after a wildcard query works' do
|
174
|
+
if ActiveRecord::VERSION::MAJOR >= 4
|
175
|
+
expect(Author.where("name like '%av%'").where.any_of({name: 'David'}, {name: 'Mary'})).to match_array([authors(:david)])
|
176
|
+
else
|
177
|
+
expect(Author.where("name like '%av%'").any_of({name: 'David'}, {name: 'Mary'})).to match_array([authors(:david)])
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'calling #any_of with a single Hash as parameter expands it' do
|
182
|
+
if ActiveRecord::VERSION::MAJOR >= 4
|
183
|
+
expect(Author.where.any_of(name: 'David', id: 2)).to match_array(authors(:david, :mary))
|
184
|
+
else
|
185
|
+
expect(Author.any_of(name: 'David', id: 2)).to match_array(authors(:david, :mary))
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
if ActiveRecord::VERSION::MAJOR >= 4
|
190
|
+
it 'calling directly #any_of is deprecated in rails-4' do
|
191
|
+
allow(ActiveSupport::Deprecation).to receive(:warn)
|
192
|
+
Author.any_of({name: 'David'}, {name: 'Mary'})
|
193
|
+
expect(ActiveSupport::Deprecation).to have_received(:warn)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
sqlite3:
|
2
|
+
adapter: <%= "jdbc" if defined? JRUBY_VERSION %>sqlite3
|
3
|
+
database: activerecord_any_of.sqlite3.db
|
4
|
+
sqlite3mem:
|
5
|
+
adapter: <%= "jdbc" if defined? JRUBY_VERSION %>sqlite3
|
6
|
+
database: ":memory:"
|
7
|
+
postgresql:
|
8
|
+
adapter: postgresql
|
9
|
+
encoding: unicode
|
10
|
+
database: activerecord_any_of_test
|
11
|
+
pool: 5
|
12
|
+
username: postgres
|
13
|
+
password:
|
14
|
+
min_messages: warning
|
15
|
+
mysql:
|
16
|
+
adapter: <%= defined?(JRUBY_VERSION) ? "jdbcmysql" : "mysql2" %>
|
17
|
+
host: localhost
|
18
|
+
username: root
|
19
|
+
password:
|
20
|
+
database: activerecord_any_of_test
|
21
|
+
encoding: utf8
|
22
|
+
## Add DB Configuration to run Oracle tests
|
23
|
+
oracle:
|
24
|
+
adapter: oracle_enhanced
|
25
|
+
host: localhost
|
26
|
+
username: activerecord_any_of_dev
|
27
|
+
password:
|
28
|
+
database: xe
|
data/spec/db/schema.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
ActiveRecord::Schema.define do
|
2
|
+
create_table :authors do |t|
|
3
|
+
t.string :name
|
4
|
+
t.datetime :created_at
|
5
|
+
t.datetime :updated_at
|
6
|
+
end
|
7
|
+
|
8
|
+
create_table :posts do |t|
|
9
|
+
t.string :title
|
10
|
+
t.text :body
|
11
|
+
t.integer :author_id
|
12
|
+
t.string :type
|
13
|
+
t.datetime :created_at
|
14
|
+
t.datetime :updated_at
|
15
|
+
end
|
16
|
+
|
17
|
+
create_table :companies do |t|
|
18
|
+
t.string :name
|
19
|
+
end
|
20
|
+
|
21
|
+
create_table :universities do |t|
|
22
|
+
t.string :name
|
23
|
+
end
|
24
|
+
|
25
|
+
create_table :memberships do |t|
|
26
|
+
t.references :organization, polymorphic: true
|
27
|
+
t.references :user
|
28
|
+
end
|
29
|
+
|
30
|
+
create_table :users do |t|
|
31
|
+
t.string :name
|
32
|
+
end
|
33
|
+
end
|
File without changes
|
File without changes
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
plugin_test_dir = File.dirname(__FILE__)
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'pry'
|
6
|
+
|
7
|
+
require 'logger'
|
8
|
+
require 'rails/all'
|
9
|
+
require 'active_record'
|
10
|
+
ActiveRecord::Base.logger = Logger.new(plugin_test_dir + "/debug.log")
|
11
|
+
|
12
|
+
require 'yaml'
|
13
|
+
require 'erb'
|
14
|
+
ActiveRecord::Base.configurations = YAML::load(ERB.new(IO.read(plugin_test_dir + "/db/database.yml")).result)
|
15
|
+
ActiveRecord::Base.establish_connection((ENV["DB"] ||= 'sqlite3mem').to_sym)
|
16
|
+
ActiveRecord::Migration.verbose = false
|
17
|
+
|
18
|
+
require 'combustion/database'
|
19
|
+
Combustion::Database.create_database(ActiveRecord::Base.configurations[ENV["DB"]])
|
20
|
+
load(File.join(plugin_test_dir, "db", "schema.rb"))
|
21
|
+
|
22
|
+
require 'activerecord_any_of'
|
23
|
+
require 'support/models'
|
24
|
+
|
25
|
+
require 'action_controller'
|
26
|
+
require 'rspec/rails'
|
27
|
+
require 'database_cleaner'
|
28
|
+
RSpec.configure do |config|
|
29
|
+
config.fixture_path = "#{plugin_test_dir}/fixtures"
|
30
|
+
config.use_transactional_fixtures = true
|
31
|
+
config.after(:suite) do
|
32
|
+
unless /sqlite/ === ENV['DB']
|
33
|
+
Combustion::Database.drop_database(ActiveRecord::Base.configurations[ENV['DB']])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class Author < ActiveRecord::Base
|
2
|
+
has_many :posts
|
3
|
+
end
|
4
|
+
|
5
|
+
class Post < ActiveRecord::Base
|
6
|
+
belongs_to :author
|
7
|
+
end
|
8
|
+
|
9
|
+
class SpecialPost < Post
|
10
|
+
end
|
11
|
+
|
12
|
+
class StiPost < Post
|
13
|
+
end
|
14
|
+
|
15
|
+
class User < ActiveRecord::Base
|
16
|
+
has_many :memberships
|
17
|
+
has_many :companies, through: :memberships, source: :organization, source_type: "Company"
|
18
|
+
has_many :universities, through: :memberships, source: :organization, source_type: "University"
|
19
|
+
end
|
20
|
+
|
21
|
+
class Membership < ActiveRecord::Base
|
22
|
+
belongs_to :user
|
23
|
+
belongs_to :organization, polymorphic: true
|
24
|
+
end
|
25
|
+
|
26
|
+
class Company < ActiveRecord::Base
|
27
|
+
has_many :memberships, as: :organization
|
28
|
+
has_many :users, through: :memberships
|
29
|
+
end
|
30
|
+
|
31
|
+
class University < ActiveRecord::Base
|
32
|
+
has_many :memberships, as: :organization
|
33
|
+
has_many :users, through: :memberships
|
34
|
+
end
|