activerecord_any_of 1.2 → 1.3

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.
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