ransack 1.8.10 → 2.0.0

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 (76) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -1
  3. data/.travis.yml +12 -3
  4. data/CHANGELOG.md +29 -5
  5. data/Gemfile +1 -9
  6. data/README.md +16 -25
  7. data/Rakefile +1 -22
  8. data/lib/polyamorous.rb +5 -18
  9. data/lib/polyamorous/activerecord_5.1_ruby_2/join_dependency.rb +2 -2
  10. data/lib/polyamorous/activerecord_5.2.0_ruby_2/join_dependency.rb +2 -2
  11. data/lib/polyamorous/activerecord_5.2.1_ruby_2/join_association.rb +38 -0
  12. data/lib/polyamorous/activerecord_5.2.1_ruby_2/join_dependency.rb +75 -0
  13. data/lib/ransack/adapters/active_record.rb +0 -9
  14. data/lib/ransack/adapters/active_record/base.rb +8 -0
  15. data/lib/ransack/adapters/active_record/context.rb +118 -182
  16. data/lib/ransack/adapters/active_record/ransack/context.rb +1 -8
  17. data/lib/ransack/adapters/active_record/ransack/translate.rb +1 -5
  18. data/lib/ransack/constants.rb +1 -1
  19. data/lib/ransack/context.rb +4 -0
  20. data/lib/ransack/nodes/value.rb +1 -1
  21. data/lib/ransack/search.rb +1 -1
  22. data/lib/ransack/version.rb +1 -1
  23. data/ransack.gemspec +4 -3
  24. data/spec/helpers/polyamorous_helper.rb +7 -9
  25. data/spec/ransack/adapters/active_record/base_spec.rb +35 -0
  26. data/spec/ransack/adapters/active_record/context_spec.rb +3 -6
  27. data/spec/ransack/helpers/form_builder_spec.rb +3 -15
  28. data/spec/ransack/helpers/form_helper_spec.rb +11 -99
  29. data/spec/ransack/join_association_spec.rb +1 -6
  30. data/spec/ransack/join_dependency_spec.rb +1 -6
  31. data/spec/ransack/search_spec.rb +2 -2
  32. data/spec/support/schema.rb +3 -21
  33. metadata +10 -83
  34. data/lib/polyamorous/activerecord_3_and_4.0_ruby_1.9/join_association.rb +0 -76
  35. data/lib/polyamorous/activerecord_3_and_4.0_ruby_1.9/join_dependency.rb +0 -96
  36. data/lib/polyamorous/activerecord_4.1_ruby_1.9/join_association.rb +0 -2
  37. data/lib/polyamorous/activerecord_4.1_ruby_1.9/join_dependency.rb +0 -4
  38. data/lib/polyamorous/activerecord_4.1_ruby_2/join_association.rb +0 -2
  39. data/lib/polyamorous/activerecord_4.1_ruby_2/join_dependency.rb +0 -3
  40. data/lib/polyamorous/activerecord_4.1_ruby_2/make_polyamorous_inner_joins.rb +0 -14
  41. data/lib/polyamorous/activerecord_4.2_ruby_1.9/join_association.rb +0 -46
  42. data/lib/polyamorous/activerecord_4.2_ruby_1.9/join_dependency.rb +0 -87
  43. data/lib/polyamorous/activerecord_4.2_ruby_2/join_association.rb +0 -2
  44. data/lib/polyamorous/activerecord_4.2_ruby_2/join_dependency.rb +0 -24
  45. data/lib/ransack/adapters/active_record/3.0/compat.rb +0 -173
  46. data/lib/ransack/adapters/active_record/3.0/context.rb +0 -203
  47. data/lib/ransack/adapters/active_record/3.1/context.rb +0 -212
  48. data/lib/ransack/adapters/active_record/3.2/context.rb +0 -44
  49. data/lib/ransack/adapters/mongoid.rb +0 -15
  50. data/lib/ransack/adapters/mongoid/3.2/.gitkeep +0 -0
  51. data/lib/ransack/adapters/mongoid/attributes/attribute.rb +0 -37
  52. data/lib/ransack/adapters/mongoid/attributes/order_predications.rb +0 -17
  53. data/lib/ransack/adapters/mongoid/attributes/predications.rb +0 -141
  54. data/lib/ransack/adapters/mongoid/base.rb +0 -134
  55. data/lib/ransack/adapters/mongoid/context.rb +0 -212
  56. data/lib/ransack/adapters/mongoid/inquiry_hash.rb +0 -23
  57. data/lib/ransack/adapters/mongoid/ransack/constants.rb +0 -88
  58. data/lib/ransack/adapters/mongoid/ransack/context.rb +0 -59
  59. data/lib/ransack/adapters/mongoid/ransack/nodes/condition.rb +0 -22
  60. data/lib/ransack/adapters/mongoid/ransack/translate.rb +0 -13
  61. data/lib/ransack/adapters/mongoid/ransack/visitor.rb +0 -18
  62. data/lib/ransack/adapters/mongoid/table.rb +0 -35
  63. data/spec/mongoid/adapters/mongoid/base_spec.rb +0 -314
  64. data/spec/mongoid/adapters/mongoid/context_spec.rb +0 -56
  65. data/spec/mongoid/configuration_spec.rb +0 -162
  66. data/spec/mongoid/dependencies_spec.rb +0 -8
  67. data/spec/mongoid/helpers/ransack_helper.rb +0 -11
  68. data/spec/mongoid/nodes/condition_spec.rb +0 -49
  69. data/spec/mongoid/nodes/grouping_spec.rb +0 -13
  70. data/spec/mongoid/predicate_spec.rb +0 -155
  71. data/spec/mongoid/search_spec.rb +0 -445
  72. data/spec/mongoid/support/mongoid.yml +0 -11
  73. data/spec/mongoid/support/schema.rb +0 -135
  74. data/spec/mongoid/translate_spec.rb +0 -14
  75. data/spec/mongoid_spec_helper.rb +0 -63
  76. data/spec/ransack/dependencies_spec.rb +0 -12
@@ -28,7 +28,7 @@ module Ransack
28
28
  name = attr.arel_attribute.name.to_s
29
29
  table = attr.arel_attribute.relation.table_name
30
30
  schema_cache = self.klass.connection.schema_cache
31
- unless schema_cache.send(database_table_exists?, table)
31
+ unless schema_cache.send(:data_source_exists?, table)
32
32
  raise "No table named #{table} exists."
33
33
  end
34
34
  attr.klass.columns.find { |column| column.name == name }.type
@@ -82,58 +82,32 @@ module Ransack
82
82
  end
83
83
  end
84
84
 
85
- if ::ActiveRecord::VERSION::STRING >= Constants::RAILS_4_1
86
-
87
- def join_associations
88
- raise NotImplementedError,
89
- "ActiveRecord 4.1 and later does not use join_associations. Use join_sources."
90
- end
91
-
92
- # All dependent Arel::Join nodes used in the search query.
93
- #
94
- # This could otherwise be done as `@object.arel.join_sources`, except
95
- # that ActiveRecord's build_joins sets up its own JoinDependency.
96
- # This extracts what we need to access the joins using our existing
97
- # JoinDependency to track table aliases.
98
- #
99
- def join_sources
100
- base, joins =
101
- if ::ActiveRecord::VERSION::MAJOR >= 5
102
- [
103
- Arel::SelectManager.new(@object.table),
104
- @join_dependency.join_constraints(@object.joins_values, @join_type)
105
- ]
106
- else
107
- [
108
- Arel::SelectManager.new(@object.engine, @object.table),
109
- @join_dependency.join_constraints(@object.joins_values)
110
- ]
111
- end
112
- joins.each do |aliased_join|
113
- base.from(aliased_join)
114
- end
115
- base.join_sources
116
- end
117
-
118
- else
119
-
120
- # All dependent JoinAssociation items used in the search query.
121
- #
122
- # Deprecated: this goes away in ActiveRecord 4.1. Use join_sources.
123
- #
124
- def join_associations
125
- @join_dependency.join_associations
85
+ # All dependent Arel::Join nodes used in the search query.
86
+ #
87
+ # This could otherwise be done as `@object.arel.join_sources`, except
88
+ # that ActiveRecord's build_joins sets up its own JoinDependency.
89
+ # This extracts what we need to access the joins using our existing
90
+ # JoinDependency to track table aliases.
91
+ #
92
+ def join_sources
93
+ base, joins =
94
+ if ::ActiveRecord::VERSION::STRING > Constants::RAILS_5_2_0
95
+ alias_tracker = ::ActiveRecord::Associations::AliasTracker.create(self.klass.connection, @object.table.name, [])
96
+ [
97
+ Arel::SelectManager.new(@object.table),
98
+ @join_dependency.join_constraints(@object.joins_values, @join_type, alias_tracker)
99
+ ]
100
+ else
101
+ [
102
+ Arel::SelectManager.new(@object.table),
103
+ @join_dependency.join_constraints(@object.joins_values, @join_type)
104
+ ]
126
105
  end
127
-
128
- def join_sources
129
- base = Arel::SelectManager.new(@object.engine, @object.table)
130
- joins = @object.joins_values
131
- joins.each do |assoc|
132
- assoc.join_to(base)
133
- end
134
- base.join_sources
106
+ joins = joins.collect(&:joins).flatten if ::ActiveRecord::VERSION::STRING < Constants::RAILS_5_2
107
+ joins.each do |aliased_join|
108
+ base.from(aliased_join)
135
109
  end
136
-
110
+ base.join_sources
137
111
  end
138
112
 
139
113
  def alias_tracker
@@ -144,22 +118,14 @@ module Ransack
144
118
  @lock_associations << association
145
119
  end
146
120
 
147
- if ::ActiveRecord::VERSION::STRING >= Constants::RAILS_4_1
148
- def remove_association(association)
149
- return if @lock_associations.include?(association)
150
- @join_dependency.instance_variable_get(:@join_root).children.delete_if { |stashed|
151
- stashed.eql?(association)
152
- }
153
- @object.joins_values.delete_if { |jd|
154
- jd.instance_variable_get(:@join_root).children.map(&:object_id) == [association.object_id]
155
- }
156
- end
157
- else
158
- def remove_association(association)
159
- return if @lock_associations.include?(association)
160
- @join_dependency.join_parts.delete(association)
161
- @object.joins_values.delete(association)
162
- end
121
+ def remove_association(association)
122
+ return if @lock_associations.include?(association)
123
+ @join_dependency.instance_variable_get(:@join_root).children.delete_if { |stashed|
124
+ stashed.eql?(association)
125
+ }
126
+ @object.joins_values.delete_if { |jd|
127
+ jd.instance_variable_get(:@join_root).children.map(&:object_id) == [association.object_id]
128
+ }
163
129
  end
164
130
 
165
131
  # Build an Arel subquery that selects keys for the top query,
@@ -199,14 +165,6 @@ module Ransack
199
165
 
200
166
  private
201
167
 
202
- def database_table_exists?
203
- if ::ActiveRecord::VERSION::MAJOR >= 5
204
- :data_source_exists?
205
- else
206
- :table_exists?
207
- end
208
- end
209
-
210
168
  def get_parent_and_attribute_name(str, parent = @base)
211
169
  attr_name = nil
212
170
 
@@ -251,8 +209,7 @@ module Ransack
251
209
  # Checkout active_record/relation/query_methods.rb +build_joins+ for
252
210
  # reference. Lots of duplicated code maybe we can avoid it
253
211
  def build_joins(relation)
254
- buckets = relation.joins_values
255
- buckets += relation.left_outer_joins_values if ::ActiveRecord::VERSION::MAJOR >= 5
212
+ buckets = relation.joins_values + relation.left_outer_joins_values
256
213
 
257
214
  buckets = buckets.group_by do |join|
258
215
  case join
@@ -275,33 +232,28 @@ module Ransack
275
232
  string_joins = buckets[:string_join].map(&:strip)
276
233
  string_joins.uniq!
277
234
 
278
- join_list =
279
- if ::ActiveRecord::VERSION::MAJOR >= 5
280
- join_nodes +
281
- convert_join_strings_to_ast(relation.table, string_joins)
282
- else
283
- relation.send :custom_join_ast,
284
- relation.table.from(relation.table), string_joins
285
- end
235
+ join_list = join_nodes + convert_join_strings_to_ast(relation.table, string_joins)
286
236
 
287
- if ::ActiveRecord::VERSION::STRING < Constants::RAILS_5_2
237
+ if ::ActiveRecord::VERSION::STRING < Constants::RAILS_5_2_0
288
238
  join_dependency = JoinDependency.new(relation.klass, association_joins, join_list)
289
239
  join_nodes.each do |join|
290
240
  join_dependency.send(:alias_tracker).aliases[join.left.name.downcase] = 1
291
241
  end
292
- else
242
+ elsif ::ActiveRecord::VERSION::STRING == Constants::RAILS_5_2_0
293
243
  alias_tracker = ::ActiveRecord::Associations::AliasTracker.create(self.klass.connection, relation.table.name, join_list)
294
244
  join_dependency = JoinDependency.new(relation.klass, relation.table, association_joins, alias_tracker)
295
245
  join_nodes.each do |join|
296
246
  join_dependency.send(:alias_tracker).aliases[join.left.name.downcase] = 1
297
247
  end
298
- end
299
-
300
- if ::ActiveRecord::VERSION::STRING >= Constants::RAILS_4_1
301
- join_dependency
302
248
  else
303
- join_dependency.graft(*stashed_association_joins)
249
+ alias_tracker = ::ActiveRecord::Associations::AliasTracker.create(self.klass.connection, relation.table.name, join_list)
250
+ join_dependency = JoinDependency.new(relation.klass, relation.table, association_joins)
251
+ join_dependency.instance_variable_set(:@alias_tracker, alias_tracker)
252
+ join_nodes.each do |join|
253
+ join_dependency.send(:alias_tracker).aliases[join.left.name.downcase] = 1
254
+ end
304
255
  end
256
+ join_dependency
305
257
  end
306
258
 
307
259
  def convert_join_strings_to_ast(table, joins)
@@ -314,109 +266,93 @@ module Ransack
314
266
  find_association(name, parent, klass) or build_association(name, parent, klass)
315
267
  end
316
268
 
317
- if ::ActiveRecord::VERSION::STRING >= Constants::RAILS_4_1
318
-
319
- def find_association(name, parent = @base, klass = nil)
320
- @join_dependency.instance_variable_get(:@join_root).children.detect do |assoc|
321
- assoc.reflection.name == name &&
322
- (@associations_pot.empty? || @associations_pot[assoc] == parent) &&
323
- (!klass || assoc.reflection.klass == klass)
324
- end
269
+ def find_association(name, parent = @base, klass = nil)
270
+ @join_dependency.instance_variable_get(:@join_root).children.detect do |assoc|
271
+ assoc.reflection.name == name &&
272
+ (@associations_pot.empty? || @associations_pot[assoc] == parent || !@associations_pot.key?(assoc)) &&
273
+ (!klass || assoc.reflection.klass == klass)
325
274
  end
275
+ end
326
276
 
327
- def build_association(name, parent = @base, klass = nil)
328
- if ::ActiveRecord::VERSION::STRING < Constants::RAILS_5_2
329
- jd = JoinDependency.new(
330
- parent.base_klass,
331
- Polyamorous::Join.new(name, @join_type, klass),
332
- []
333
- )
334
- found_association = jd.join_root.children.last
335
- else
336
- alias_tracker = ::ActiveRecord::Associations::AliasTracker.create(self.klass.connection, parent.table.name, [])
337
- jd = JoinDependency.new(
338
- parent.base_klass,
339
- parent.base_klass.arel_table,
340
- Polyamorous::Join.new(name, @join_type, klass),
341
- alias_tracker
342
- )
343
- found_association = jd.instance_variable_get(:@join_root).children.last
344
- end
277
+ def build_association(name, parent = @base, klass = nil)
278
+ if ::ActiveRecord::VERSION::STRING < Constants::RAILS_5_2_0
279
+ jd = JoinDependency.new(
280
+ parent.base_klass,
281
+ Polyamorous::Join.new(name, @join_type, klass),
282
+ []
283
+ )
284
+ found_association = jd.join_root.children.last
285
+ elsif ::ActiveRecord::VERSION::STRING == Constants::RAILS_5_2_0
286
+ alias_tracker = ::ActiveRecord::Associations::AliasTracker.create(self.klass.connection, parent.table.name, [])
287
+ jd = JoinDependency.new(
288
+ parent.base_klass,
289
+ parent.base_klass.arel_table,
290
+ Polyamorous::Join.new(name, @join_type, klass),
291
+ alias_tracker
292
+ )
293
+ found_association = jd.instance_variable_get(:@join_root).children.last
294
+ else
295
+ jd = JoinDependency.new(
296
+ parent.base_klass,
297
+ parent.base_klass.arel_table,
298
+ Polyamorous::Join.new(name, @join_type, klass),
299
+ )
300
+ found_association = jd.instance_variable_get(:@join_root).children.last
301
+ end
345
302
 
346
303
 
347
- @associations_pot[found_association] = parent
304
+ @associations_pot[found_association] = parent
348
305
 
349
- # TODO maybe we dont need to push associations here, we could loop
350
- # through the @associations_pot instead
351
- @join_dependency.instance_variable_get(:@join_root).children.push found_association
306
+ # TODO maybe we dont need to push associations here, we could loop
307
+ # through the @associations_pot instead
308
+ @join_dependency.instance_variable_get(:@join_root).children.push found_association
352
309
 
353
- # Builds the arel nodes properly for this association
310
+ # Builds the arel nodes properly for this association
311
+ if ::ActiveRecord::VERSION::STRING > Constants::RAILS_5_2_0
312
+ @join_dependency.send(:construct_tables!, jd.instance_variable_get(:@join_root))
313
+ else
354
314
  @join_dependency.send(
355
315
  :construct_tables!, jd.instance_variable_get(:@join_root), found_association
356
- )
357
-
358
- # Leverage the stashed association functionality in AR
359
- @object = @object.joins(jd)
360
-
361
- found_association
362
- end
363
-
364
- def extract_joins(association)
365
- parent = @join_dependency.instance_variable_get(:@join_root)
366
- reflection = association.reflection
367
- join_constraints = if ::ActiveRecord::VERSION::STRING < Constants::RAILS_5_1
368
- association.join_constraints(
369
- parent.table,
370
- parent.base_klass,
371
- association,
372
- Arel::Nodes::OuterJoin,
373
- association.tables,
374
- reflection.scope_chain,
375
- reflection.chain
376
- )
377
- else
378
- association.join_constraints(
379
- parent.table,
380
- parent.base_klass,
381
- Arel::Nodes::OuterJoin,
382
- association.tables,
383
- reflection.chain
384
- )
385
- end
386
- join_constraints.to_a.flatten
387
- end
388
-
389
- else
390
-
391
- def build_association(name, parent = @base, klass = nil)
392
- @join_dependency.send(
393
- :build,
394
- Polyamorous::Join.new(name, @join_type, klass),
395
- parent
396
- )
397
- found_association = @join_dependency.join_associations.last
398
- # Leverage the stashed association functionality in AR
399
- @object = @object.joins(found_association)
400
-
401
- found_association
316
+ )
402
317
  end
403
318
 
404
- def extract_joins(association)
405
- query = Arel::SelectManager.new(association.base_klass, association.table)
406
- association.join_to(query).join_sources
407
- end
408
-
409
- def find_association(name, parent = @base, klass = nil)
410
- @join_dependency.join_associations
411
- .detect do |assoc|
412
- assoc.reflection.name == name &&
413
- assoc.parent == parent &&
414
- (!klass || assoc.reflection.klass == klass)
415
- end
416
- end
319
+ # Leverage the stashed association functionality in AR
320
+ @object = @object.joins(jd)
417
321
 
322
+ found_association
418
323
  end
419
324
 
325
+ def extract_joins(association)
326
+ parent = @join_dependency.instance_variable_get(:@join_root)
327
+ reflection = association.reflection
328
+ join_constraints = if ::ActiveRecord::VERSION::STRING < Constants::RAILS_5_1
329
+ association.join_constraints(
330
+ parent.table,
331
+ parent.base_klass,
332
+ association,
333
+ Arel::Nodes::OuterJoin,
334
+ association.tables,
335
+ reflection.scope_chain,
336
+ reflection.chain
337
+ )
338
+ elsif ::ActiveRecord::VERSION::STRING <= Constants::RAILS_5_2_0
339
+ association.join_constraints(
340
+ parent.table,
341
+ parent.base_klass,
342
+ Arel::Nodes::OuterJoin,
343
+ association.tables,
344
+ reflection.chain
345
+ )
346
+ else
347
+ association.join_constraints(
348
+ parent.table,
349
+ parent.base_klass,
350
+ Arel::Nodes::OuterJoin,
351
+ @join_dependency.instance_variable_get(:@alias_tracker)
352
+ )
353
+ end
354
+ join_constraints.to_a.flatten
355
+ end
420
356
  end
421
357
  end
422
358
  end
@@ -32,12 +32,9 @@ module Ransack
32
32
 
33
33
  if ::ActiveRecord::VERSION::STRING >= Constants::RAILS_5_2
34
34
  @base = @join_dependency.instance_variable_get(:@join_root)
35
- elsif ::ActiveRecord::VERSION::STRING >= Constants::RAILS_4_1
35
+ else
36
36
  @base = @join_dependency.join_root
37
37
  @engine = @base.base_klass.arel_engine
38
- else
39
- @base = @join_dependency.join_base
40
- @engine = @base.arel_engine
41
38
  end
42
39
  end
43
40
 
@@ -55,10 +52,6 @@ module Ransack
55
52
  obj
56
53
  elsif obj.respond_to? :klass
57
54
  obj.klass
58
- elsif obj.respond_to? :active_record # Rails 3
59
- obj.active_record
60
- elsif obj.respond_to? :base_klass # Rails 4
61
- obj.base_klass
62
55
  else
63
56
  raise ArgumentError, "Don't know how to klassify #{obj.inspect}"
64
57
  end
@@ -2,11 +2,7 @@ module Ransack
2
2
  module Translate
3
3
 
4
4
  def self.i18n_key(klass)
5
- if ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR == 0
6
- klass.model_name.i18n_key.to_s.tr('.'.freeze, '/'.freeze)
7
- else
8
- klass.model_name.i18n_key.to_s.freeze
9
- end
5
+ klass.model_name.i18n_key.to_s.freeze
10
6
  end
11
7
  end
12
8
  end
@@ -45,9 +45,9 @@ module Ransack
45
45
  NOT_EQ_ALL = 'not_eq_all'.freeze
46
46
  CONT = 'cont'.freeze
47
47
 
48
- RAILS_4_1 = '4.1'.freeze
49
48
  RAILS_5_1 = '5.1'.freeze
50
49
  RAILS_5_2 = '5.2'.freeze
50
+ RAILS_5_2_0 = '5.2.0'.freeze
51
51
 
52
52
  RANSACK_SLASH_SEARCHES = 'ransack/searches'.freeze
53
53
  RANSACK_SLASH_SEARCHES_SLASH_SEARCH = 'ransack/searches/search'.freeze
@@ -138,6 +138,10 @@ module Ransack
138
138
  klass.ransackable_scopes(auth_object).any? { |s| s.to_sym == str.to_sym }
139
139
  end
140
140
 
141
+ def ransackable_scope_skip_sanitize_args?(str, klass)
142
+ klass.ransackable_scopes_skip_sanitize_args.any? { |s| s.to_sym == str.to_sym }
143
+ end
144
+
141
145
  def searchable_attributes(str = ''.freeze)
142
146
  traverse(str).ransackable_attributes(auth_object)
143
147
  end
@@ -98,7 +98,7 @@ module Ransack
98
98
  val.to_s.to_d
99
99
  end
100
100
  end
101
-
101
+
102
102
  def cast_to_money(val)
103
103
  val.blank? ? nil : val.to_f.to_s
104
104
  end
@@ -123,7 +123,7 @@ module Ransack
123
123
  private
124
124
 
125
125
  def add_scope(key, args)
126
- sanitized_args = if Ransack.options[:sanitize_scope_args]
126
+ sanitized_args = if Ransack.options[:sanitize_scope_args] && !@context.ransackable_scope_skip_sanitize_args?(key, @context.object)
127
127
  sanitized_scope_args(args)
128
128
  else
129
129
  args