activerecord_any_of 1.2 → 1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -38
  3. data/Rakefile +9 -27
  4. data/lib/activerecord_any_of/alternative_builder.rb +25 -9
  5. data/lib/activerecord_any_of/version.rb +1 -1
  6. data/lib/activerecord_any_of.rb +4 -4
  7. data/spec/activerecord_any_of_spec.rb +196 -0
  8. data/spec/db/database.yml +28 -0
  9. data/spec/db/schema.rb +33 -0
  10. data/{test → spec}/fixtures/authors.yml +0 -0
  11. data/{test → spec}/fixtures/posts.yml +0 -0
  12. data/spec/fixtures/users.yml +9 -0
  13. data/spec/spec_helper.rb +36 -0
  14. data/spec/support/models.rb +34 -0
  15. metadata +76 -203
  16. data/test/activerecord_any_of_test.rb +0 -114
  17. data/test/dummy_rails3/README.rdoc +0 -261
  18. data/test/dummy_rails3/Rakefile +0 -7
  19. data/test/dummy_rails3/app/assets/javascripts/application.js +0 -15
  20. data/test/dummy_rails3/app/assets/stylesheets/application.css +0 -13
  21. data/test/dummy_rails3/app/controllers/application_controller.rb +0 -3
  22. data/test/dummy_rails3/app/helpers/application_helper.rb +0 -2
  23. data/test/dummy_rails3/app/models/author.rb +0 -4
  24. data/test/dummy_rails3/app/models/post.rb +0 -4
  25. data/test/dummy_rails3/app/models/special_post.rb +0 -2
  26. data/test/dummy_rails3/app/models/sti_post.rb +0 -2
  27. data/test/dummy_rails3/app/views/layouts/application.html.erb +0 -14
  28. data/test/dummy_rails3/config/application.rb +0 -59
  29. data/test/dummy_rails3/config/boot.rb +0 -10
  30. data/test/dummy_rails3/config/database.yml +0 -25
  31. data/test/dummy_rails3/config/environment.rb +0 -5
  32. data/test/dummy_rails3/config/environments/development.rb +0 -37
  33. data/test/dummy_rails3/config/environments/production.rb +0 -67
  34. data/test/dummy_rails3/config/environments/test.rb +0 -37
  35. data/test/dummy_rails3/config/initializers/backtrace_silencers.rb +0 -7
  36. data/test/dummy_rails3/config/initializers/inflections.rb +0 -15
  37. data/test/dummy_rails3/config/initializers/mime_types.rb +0 -5
  38. data/test/dummy_rails3/config/initializers/secret_token.rb +0 -7
  39. data/test/dummy_rails3/config/initializers/session_store.rb +0 -8
  40. data/test/dummy_rails3/config/initializers/wrap_parameters.rb +0 -14
  41. data/test/dummy_rails3/config/locales/en.yml +0 -5
  42. data/test/dummy_rails3/config/routes.rb +0 -58
  43. data/test/dummy_rails3/config.ru +0 -4
  44. data/test/dummy_rails3/db/development.sqlite3 +0 -0
  45. data/test/dummy_rails3/db/migrate/20130617172335_create_authors.rb +0 -9
  46. data/test/dummy_rails3/db/migrate/20130617173313_create_posts.rb +0 -12
  47. data/test/dummy_rails3/db/schema.rb +0 -31
  48. data/test/dummy_rails3/db/test.sqlite3 +0 -0
  49. data/test/dummy_rails3/log/development.log +0 -101
  50. data/test/dummy_rails3/log/test.log +0 -2875
  51. data/test/dummy_rails3/public/404.html +0 -26
  52. data/test/dummy_rails3/public/422.html +0 -26
  53. data/test/dummy_rails3/public/500.html +0 -25
  54. data/test/dummy_rails3/public/favicon.ico +0 -0
  55. data/test/dummy_rails3/script/rails +0 -6
  56. data/test/dummy_rails3/test/fixtures/authors.yml +0 -7
  57. data/test/dummy_rails3/test/fixtures/posts.yml +0 -13
  58. data/test/dummy_rails3/test/unit/author_test.rb +0 -7
  59. data/test/dummy_rails3/test/unit/post_test.rb +0 -7
  60. data/test/dummy_rails4/README.rdoc +0 -28
  61. data/test/dummy_rails4/Rakefile +0 -6
  62. data/test/dummy_rails4/app/assets/javascripts/application.js +0 -13
  63. data/test/dummy_rails4/app/assets/stylesheets/application.css +0 -13
  64. data/test/dummy_rails4/app/controllers/application_controller.rb +0 -5
  65. data/test/dummy_rails4/app/helpers/application_helper.rb +0 -2
  66. data/test/dummy_rails4/app/models/author.rb +0 -3
  67. data/test/dummy_rails4/app/models/post.rb +0 -3
  68. data/test/dummy_rails4/app/models/special_post.rb +0 -2
  69. data/test/dummy_rails4/app/models/sti_post.rb +0 -2
  70. data/test/dummy_rails4/app/views/layouts/application.html.erb +0 -14
  71. data/test/dummy_rails4/bin/bundle +0 -3
  72. data/test/dummy_rails4/bin/rails +0 -4
  73. data/test/dummy_rails4/bin/rake +0 -4
  74. data/test/dummy_rails4/config/application.rb +0 -23
  75. data/test/dummy_rails4/config/boot.rb +0 -5
  76. data/test/dummy_rails4/config/database.yml +0 -25
  77. data/test/dummy_rails4/config/environment.rb +0 -5
  78. data/test/dummy_rails4/config/environments/development.rb +0 -29
  79. data/test/dummy_rails4/config/environments/production.rb +0 -80
  80. data/test/dummy_rails4/config/environments/test.rb +0 -36
  81. data/test/dummy_rails4/config/initializers/backtrace_silencers.rb +0 -7
  82. data/test/dummy_rails4/config/initializers/filter_parameter_logging.rb +0 -4
  83. data/test/dummy_rails4/config/initializers/inflections.rb +0 -16
  84. data/test/dummy_rails4/config/initializers/mime_types.rb +0 -5
  85. data/test/dummy_rails4/config/initializers/secret_token.rb +0 -12
  86. data/test/dummy_rails4/config/initializers/session_store.rb +0 -3
  87. data/test/dummy_rails4/config/initializers/wrap_parameters.rb +0 -14
  88. data/test/dummy_rails4/config/locales/en.yml +0 -23
  89. data/test/dummy_rails4/config/routes.rb +0 -56
  90. data/test/dummy_rails4/config.ru +0 -4
  91. data/test/dummy_rails4/db/development.sqlite3 +0 -0
  92. data/test/dummy_rails4/db/migrate/20130617172335_create_authors.rb +0 -9
  93. data/test/dummy_rails4/db/migrate/20130617173313_create_posts.rb +0 -12
  94. data/test/dummy_rails4/db/schema.rb +0 -31
  95. data/test/dummy_rails4/db/test.sqlite3 +0 -0
  96. data/test/dummy_rails4/log/development.log +0 -21
  97. data/test/dummy_rails4/log/test.log +0 -1527
  98. data/test/dummy_rails4/public/404.html +0 -58
  99. data/test/dummy_rails4/public/422.html +0 -58
  100. data/test/dummy_rails4/public/500.html +0 -57
  101. data/test/dummy_rails4/public/favicon.ico +0 -0
  102. data/test/dummy_rails4/test/fixtures/authors.yml +0 -7
  103. data/test/dummy_rails4/test/fixtures/posts.yml +0 -13
  104. data/test/dummy_rails4/test/unit/author_test.rb +0 -7
  105. data/test/dummy_rails4/test/unit/post_test.rb +0 -7
  106. data/test/test_helper.rb +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5047c28acc2012bdd8941d946180d5587354567b
4
- data.tar.gz: fb3a7ec4a6a999b8c7b5877ee3317bdcd9a37912
3
+ metadata.gz: 3086cee8dc2889c8e3f8874ef32631af08c750c2
4
+ data.tar.gz: 5e01aa2499c952e4fc215c24890b215d1749f104
5
5
  SHA512:
6
- metadata.gz: 723692244e87973207876e3b0e065c3ebe11f461f58b463a2270410fe6ece1cc2925a9ef3ee44b1f54a424f1cddba2cd5b15a8556fe43720541e2176a4c9e9f5
7
- data.tar.gz: e4e673618cb1354433b5e374ecc966464a63b0b770a64931fa80216a494a9f8460b3f8f0a95754969a17f1c4710bd5941c7158eee816fc359467ec7707ff11ef
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
- Activerecord_any_of allows to run tests against both rails-3 and rails-4. You
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
- rails_version = ENV[ 'RAILS_VERSION' ] || '4'
4
+ require 'rubygems'
5
+ require 'bundler/setup'
6
+ require 'activerecord_any_of/version'
4
7
 
5
- if rails_version == '3'
6
- ENV[ 'BUNDLE_GEMFILE' ] = 'Gemfile.rails3'
7
- else
8
- ENV[ 'BUNDLE_GEMFILE' ] = 'Gemfile.rails4'
9
- end
8
+ task :default => :spec
10
9
 
11
- begin
12
- require 'bundler/setup'
13
- rescue LoadError
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 Rails.version >= '4' && query.references_values.any?
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 ||= queries_joins_values.each { |tables| tables.uniq }
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 Rails.version >= '4'
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 Rails.version >= '4'
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 Rails.version >= '4'
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 Rails.version >= '4'
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)))
@@ -1,3 +1,3 @@
1
1
  module ActiverecordAnyOf
2
- VERSION = "1.2"
2
+ VERSION = "1.3"
3
3
  end
@@ -57,7 +57,7 @@ module ActiverecordAnyOf
57
57
 
58
58
  module Deprecated
59
59
  def any_of(*queries)
60
- if Rails.version >= '4'
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 Rails.version >= '4'
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 Rails.version >= '4'
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 Rails.version >= '4'
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
@@ -0,0 +1,9 @@
1
+ ezra:
2
+ id: 1
3
+ name: "Ezra"
4
+ aria:
5
+ id: 2
6
+ name: "Aria"
7
+ james:
8
+ id: 3
9
+ name: "James"
@@ -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