ransack 1.8.10 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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