ransack 2.3.2 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +3 -0
  3. data/.github/SECURITY.md +12 -0
  4. data/.github/workflows/cronjob.yml +102 -0
  5. data/.github/workflows/rubocop.yml +20 -0
  6. data/.github/workflows/test.yml +163 -0
  7. data/.rubocop.yml +44 -0
  8. data/CHANGELOG.md +28 -1
  9. data/CONTRIBUTING.md +16 -11
  10. data/Gemfile +5 -3
  11. data/README.md +167 -30
  12. data/bug_report_templates/test-ransack-scope-and-column-same-name.rb +78 -0
  13. data/bug_report_templates/test-ransacker-arel-present-predicate.rb +71 -0
  14. data/docs/img/create_release.png +0 -0
  15. data/docs/release_process.md +17 -0
  16. data/{polyamorous/lib → lib}/polyamorous/activerecord_5.2_ruby_2/join_association.rb +4 -0
  17. data/{polyamorous/lib → lib}/polyamorous/activerecord_5.2_ruby_2/join_dependency.rb +0 -0
  18. data/lib/polyamorous/activerecord_5.2_ruby_2/reflection.rb +11 -0
  19. data/{polyamorous/lib → lib}/polyamorous/activerecord_6.0_ruby_2/join_association.rb +0 -1
  20. data/{polyamorous/lib → lib}/polyamorous/activerecord_6.0_ruby_2/join_dependency.rb +0 -1
  21. data/{polyamorous/lib → lib}/polyamorous/activerecord_6.0_ruby_2/reflection.rb +0 -1
  22. data/lib/polyamorous/activerecord_6.1_ruby_2/join_association.rb +74 -0
  23. data/lib/polyamorous/activerecord_6.1_ruby_2/join_dependency.rb +93 -0
  24. data/{polyamorous/lib → lib}/polyamorous/activerecord_6.1_ruby_2/reflection.rb +0 -1
  25. data/lib/polyamorous/activerecord_7.0_ruby_2/join_association.rb +1 -0
  26. data/lib/polyamorous/activerecord_7.0_ruby_2/join_dependency.rb +1 -0
  27. data/lib/polyamorous/activerecord_7.0_ruby_2/reflection.rb +1 -0
  28. data/{polyamorous/lib → lib}/polyamorous/join.rb +0 -0
  29. data/{polyamorous/lib → lib/polyamorous}/polyamorous.rb +1 -1
  30. data/{polyamorous/lib → lib}/polyamorous/swapping_reflection_class.rb +0 -0
  31. data/{polyamorous/lib → lib}/polyamorous/tree_node.rb +0 -0
  32. data/lib/polyamorous.rb +1 -0
  33. data/lib/ransack/adapters/active_record/base.rb +5 -1
  34. data/lib/ransack/adapters/active_record/context.rb +55 -13
  35. data/lib/ransack/adapters/active_record/ransack/constants.rb +1 -1
  36. data/lib/ransack/adapters/active_record/ransack/context.rb +1 -0
  37. data/lib/ransack/adapters/active_record/ransack/nodes/condition.rb +11 -3
  38. data/lib/ransack/configuration.rb +31 -1
  39. data/lib/ransack/constants.rb +2 -2
  40. data/lib/ransack/helpers/form_builder.rb +3 -3
  41. data/lib/ransack/helpers.rb +1 -1
  42. data/lib/ransack/locale/sv.yml +70 -0
  43. data/lib/ransack/nodes/attribute.rb +1 -1
  44. data/lib/ransack/nodes/condition.rb +0 -2
  45. data/lib/ransack/nodes/grouping.rb +1 -1
  46. data/lib/ransack/nodes/sort.rb +3 -3
  47. data/lib/ransack/nodes/value.rb +1 -1
  48. data/lib/ransack/search.rb +4 -1
  49. data/lib/ransack/translate.rb +4 -4
  50. data/lib/ransack/version.rb +1 -1
  51. data/lib/ransack.rb +2 -2
  52. data/ransack.gemspec +8 -14
  53. data/spec/blueprints/articles.rb +1 -1
  54. data/spec/blueprints/comments.rb +1 -1
  55. data/spec/blueprints/notes.rb +1 -1
  56. data/spec/blueprints/tags.rb +1 -1
  57. data/spec/console.rb +5 -5
  58. data/spec/helpers/ransack_helper.rb +1 -1
  59. data/spec/{ransack → polyamorous}/join_association_spec.rb +8 -1
  60. data/spec/{ransack → polyamorous}/join_dependency_spec.rb +0 -0
  61. data/spec/{ransack → polyamorous}/join_spec.rb +0 -0
  62. data/spec/ransack/adapters/active_record/base_spec.rb +26 -15
  63. data/spec/ransack/adapters/active_record/context_spec.rb +19 -18
  64. data/spec/ransack/configuration_spec.rb +24 -0
  65. data/spec/ransack/helpers/form_helper_spec.rb +16 -16
  66. data/spec/ransack/nodes/condition_spec.rb +13 -0
  67. data/spec/ransack/nodes/grouping_spec.rb +2 -2
  68. data/spec/ransack/predicate_spec.rb +1 -1
  69. data/spec/ransack/search_spec.rb +215 -30
  70. data/spec/spec_helper.rb +7 -5
  71. data/spec/support/schema.rb +28 -2
  72. metadata +45 -47
  73. data/.travis.yml +0 -47
  74. data/polyamorous/lib/polyamorous/activerecord_5.2_ruby_2/reflection.rb +0 -12
  75. data/polyamorous/lib/polyamorous/activerecord_6.1_ruby_2/join_association.rb +0 -2
  76. data/polyamorous/lib/polyamorous/activerecord_6.1_ruby_2/join_dependency.rb +0 -2
  77. data/polyamorous/lib/polyamorous/version.rb +0 -3
  78. data/polyamorous/polyamorous.gemspec +0 -27
@@ -18,6 +18,10 @@ module Ransack
18
18
  Search.new(self, params, options)
19
19
  end
20
20
 
21
+ def ransack!(params = {}, options = {})
22
+ ransack(params, options.merge(ignore_unknown_conditions: false))
23
+ end
24
+
21
25
  def ransacker(name, opts = {}, &block)
22
26
  self._ransackers = _ransackers.merge name.to_s => Ransacker
23
27
  .new(self, name, opts, &block)
@@ -66,7 +70,7 @@ module Ransack
66
70
  end
67
71
 
68
72
  # ransack_scope_skip_sanitize_args, by default, returns an empty array.
69
- # i.e. use the sanitize_scope_args setting to determin if args should be converted.
73
+ # i.e. use the sanitize_scope_args setting to determine if args should be converted.
70
74
  # For overriding with a list of scopes which should be passed the args as-is.
71
75
  #
72
76
  def ransackable_scopes_skip_sanitize_args
@@ -1,5 +1,5 @@
1
1
  require 'ransack/context'
2
- require 'polyamorous'
2
+ require 'polyamorous/polyamorous'
3
3
 
4
4
  module Ransack
5
5
  module Adapters
@@ -42,6 +42,17 @@ module Ransack
42
42
  if scope_or_sort.is_a?(Symbol)
43
43
  relation = relation.send(scope_or_sort)
44
44
  else
45
+ case Ransack.options[:postgres_fields_sort_option]
46
+ when :nulls_first
47
+ scope_or_sort = scope_or_sort.direction == :asc ? Arel.sql("#{scope_or_sort.to_sql} NULLS FIRST") : Arel.sql("#{scope_or_sort.to_sql} NULLS LAST")
48
+ when :nulls_last
49
+ scope_or_sort = scope_or_sort.direction == :asc ? Arel.sql("#{scope_or_sort.to_sql} NULLS LAST") : Arel.sql("#{scope_or_sort.to_sql} NULLS FIRST")
50
+ when :nulls_always_first
51
+ scope_or_sort = Arel.sql("#{scope_or_sort.to_sql} NULLS FIRST")
52
+ when :nulls_always_last
53
+ scope_or_sort = Arel.sql("#{scope_or_sort.to_sql} NULLS LAST")
54
+ end
55
+
45
56
  relation = relation.order(scope_or_sort)
46
57
  end
47
58
  end
@@ -99,7 +110,9 @@ module Ransack
99
110
  def join_sources
100
111
  base, joins = begin
101
112
  alias_tracker = ::ActiveRecord::Associations::AliasTracker.create(self.klass.connection, @object.table.name, [])
102
- constraints = if ::Gem::Version.new(::ActiveRecord::VERSION::STRING) >= ::Gem::Version.new(Constants::RAILS_6_0)
113
+ constraints = if ::Gem::Version.new(::ActiveRecord::VERSION::STRING) >= ::Gem::Version.new(Constants::RAILS_6_1)
114
+ @join_dependency.join_constraints(@object.joins_values, alias_tracker, @object.references_values)
115
+ elsif ::Gem::Version.new(::ActiveRecord::VERSION::STRING) >= ::Gem::Version.new(Constants::RAILS_6_0)
103
116
  @join_dependency.join_constraints(@object.joins_values, alias_tracker)
104
117
  else
105
118
  @join_dependency.join_constraints(@object.joins_values, @join_type, alias_tracker)
@@ -172,16 +185,31 @@ module Ransack
172
185
  private
173
186
 
174
187
  def extract_correlated_key(join_root)
175
- correlated_key = join_root.right.expr.left
176
-
177
- if correlated_key.is_a? Arel::Nodes::And
178
- correlated_key = correlated_key.left.left
179
- elsif correlated_key.is_a? Arel::Nodes::Equality
180
- correlated_key = correlated_key.left
181
- elsif correlated_key.is_a? Arel::Nodes::Grouping
182
- correlated_key = join_root.right.expr.right.left
188
+ case join_root
189
+ when Arel::Nodes::OuterJoin
190
+ # one of join_root.right/join_root.left is expected to be Arel::Nodes::On
191
+ if join_root.right.is_a?(Arel::Nodes::On)
192
+ extract_correlated_key(join_root.right.expr)
193
+ elsif join_root.left.is_a?(Arel::Nodes::On)
194
+ extract_correlated_key(join_root.left.expr)
195
+ else
196
+ raise 'Ransack encountered an unexpected arel structure'
197
+ end
198
+ when Arel::Nodes::Equality
199
+ pk = primary_key
200
+ if join_root.left == pk
201
+ join_root.right
202
+ elsif join_root.right == pk
203
+ join_root.left
204
+ else
205
+ nil
206
+ end
207
+ when Arel::Nodes::And
208
+ extract_correlated_key(join_root.left) || extract_correlated_key(join_root.right)
183
209
  else
184
- correlated_key
210
+ # eg parent was Arel::Nodes::And and the evaluated side was one of
211
+ # Arel::Nodes::Grouping or MultiTenant::TenantEnforcementClause
212
+ nil
185
213
  end
186
214
  end
187
215
 
@@ -310,7 +338,11 @@ module Ransack
310
338
  @join_dependency.instance_variable_get(:@join_root).children.push found_association
311
339
 
312
340
  # Builds the arel nodes properly for this association
313
- @join_dependency.send(:construct_tables!, jd.instance_variable_get(:@join_root))
341
+ if ::Gem::Version.new(::ActiveRecord::VERSION::STRING) >= ::Gem::Version.new(Constants::RAILS_6_1)
342
+ @tables_pot[found_association] = @join_dependency.construct_tables_for_association!(jd.instance_variable_get(:@join_root), found_association)
343
+ else
344
+ @join_dependency.send(:construct_tables!, jd.instance_variable_get(:@join_root))
345
+ end
314
346
 
315
347
  # Leverage the stashed association functionality in AR
316
348
  @object = @object.joins(jd)
@@ -320,12 +352,22 @@ module Ransack
320
352
  def extract_joins(association)
321
353
  parent = @join_dependency.instance_variable_get(:@join_root)
322
354
  reflection = association.reflection
323
- join_constraints = association.join_constraints(
355
+ join_constraints = if ::Gem::Version.new(::ActiveRecord::VERSION::STRING) >= ::Gem::Version.new(Constants::RAILS_6_1)
356
+ association.join_constraints_with_tables(
357
+ parent.table,
358
+ parent.base_klass,
359
+ Arel::Nodes::OuterJoin,
360
+ @join_dependency.instance_variable_get(:@alias_tracker),
361
+ @tables_pot[association]
362
+ )
363
+ else
364
+ association.join_constraints(
324
365
  parent.table,
325
366
  parent.base_klass,
326
367
  Arel::Nodes::OuterJoin,
327
368
  @join_dependency.instance_variable_get(:@alias_tracker)
328
369
  )
370
+ end
329
371
  join_constraints.to_a.flatten
330
372
  end
331
373
  end
@@ -97,7 +97,7 @@ module Ransack
97
97
  arel_predicate: proc { |v| v ? EQ : NOT_EQ },
98
98
  compounds: false,
99
99
  type: :boolean,
100
- validator: proc { |v| BOOLEAN_VALUES.include?(v)},
100
+ validator: proc { |v| BOOLEAN_VALUES.include?(v) },
101
101
  formatter: proc { |v| nil }
102
102
  }
103
103
  ],
@@ -28,6 +28,7 @@ module Ransack
28
28
  @join_type = options[:join_type] || Polyamorous::OuterJoin
29
29
  @search_key = options[:search_key] || Ransack.options[:search_key]
30
30
  @associations_pot = {}
31
+ @tables_pot = {}
31
32
  @lock_associations = []
32
33
 
33
34
  @base = @join_dependency.instance_variable_get(:@join_root)
@@ -47,12 +47,20 @@ module Ransack
47
47
  end
48
48
 
49
49
  def casted_array?(predicate)
50
- predicate.respond_to?(:val) && predicate.val.is_a?(Array)
50
+ value_from(predicate).is_a?(Array) && predicate.is_a?(Arel::Nodes::Casted)
51
+ end
52
+
53
+ def value_from(predicate)
54
+ if predicate.respond_to?(:value)
55
+ predicate.value # Rails 6.1
56
+ elsif predicate.respond_to?(:val)
57
+ predicate.val # Rails 5.2, 6.0
58
+ end
51
59
  end
52
60
 
53
61
  def format_values_for(predicate)
54
- predicate.val.map do |value|
55
- value.is_a?(String) ? Arel::Nodes.build_quoted(value) : value
62
+ value_from(predicate).map do |val|
63
+ val.is_a?(String) ? Arel::Nodes.build_quoted(val) : val
56
64
  end
57
65
  end
58
66
 
@@ -33,7 +33,9 @@ module Ransack
33
33
  :up_arrow => '▼'.freeze,
34
34
  :down_arrow => '▲'.freeze,
35
35
  :default_arrow => nil,
36
- :sanitize_scope_args => true
36
+ :sanitize_scope_args => true,
37
+ :postgres_fields_sort_option => nil,
38
+ :strip_whitespace => true
37
39
  }
38
40
 
39
41
  def configure
@@ -141,6 +143,21 @@ module Ransack
141
143
  self.options[:sanitize_scope_args] = boolean
142
144
  end
143
145
 
146
+ # The `NULLS FIRST` and `NULLS LAST` options can be used to determine
147
+ # whether nulls appear before or after non-null values in the sort ordering.
148
+ #
149
+ # User may want to configure it like this:
150
+ #
151
+ # Ransack.configure do |c|
152
+ # c.postgres_fields_sort_option = :nulls_first # or e.g. :nulls_always_last
153
+ # end
154
+ #
155
+ # See this feature: https://www.postgresql.org/docs/13/queries-order.html
156
+ #
157
+ def postgres_fields_sort_option=(setting)
158
+ self.options[:postgres_fields_sort_option] = setting
159
+ end
160
+
144
161
  # By default, Ransack displays sort order indicator arrows in sort links.
145
162
  # The default may be globally overridden in an initializer file like
146
163
  # `config/initializers/ransack.rb` as follows:
@@ -154,6 +171,19 @@ module Ransack
154
171
  self.options[:hide_sort_order_indicators] = boolean
155
172
  end
156
173
 
174
+ # By default, Ransack displays strips all whitespace when searching for a string.
175
+ # The default may be globally changed in an initializer file like
176
+ # `config/initializers/ransack.rb` as follows:
177
+ #
178
+ # Ransack.configure do |config|
179
+ # # Enable whitespace stripping for string searches
180
+ # config.strip_whitespace = true
181
+ # end
182
+ #
183
+ def strip_whitespace=(boolean)
184
+ self.options[:strip_whitespace] = boolean
185
+ end
186
+
157
187
  def arel_predicate_with_suffix(arel_predicate, suffix)
158
188
  if arel_predicate === Proc
159
189
  proc { |v| "#{arel_predicate.call(v)}#{suffix}" }
@@ -36,7 +36,7 @@ module Ransack
36
36
  'lt'.freeze, 'lteq'.freeze,
37
37
  'gt'.freeze, 'gteq'.freeze,
38
38
  'in'.freeze, 'not_in'.freeze
39
- ].freeze
39
+ ].freeze
40
40
  A_S_I = ['a'.freeze, 's'.freeze, 'i'.freeze].freeze
41
41
 
42
42
  EQ = 'eq'.freeze
@@ -46,9 +46,9 @@ module Ransack
46
46
  CONT = 'cont'.freeze
47
47
 
48
48
  RAILS_6_0 = '6.0.0'.freeze
49
+ RAILS_6_1 = '6.1.0'.freeze
49
50
 
50
51
  RANSACK_SLASH_SEARCHES = 'ransack/searches'.freeze
51
52
  RANSACK_SLASH_SEARCHES_SLASH_SEARCH = 'ransack/searches/search'.freeze
52
53
  end
53
54
  end
54
-
@@ -45,9 +45,9 @@ module Ransack
45
45
  end
46
46
 
47
47
  def attribute_select(options = nil, html_options = nil, action = nil)
48
- options = options || {}
49
- html_options = html_options || {}
50
- action = action || Constants::SEARCH
48
+ options ||= {}
49
+ html_options ||= {}
50
+ action ||= Constants::SEARCH
51
51
  default = options.delete(:default)
52
52
  raise ArgumentError, formbuilder_error_message(
53
53
  "#{action}_select") unless object.respond_to?(:context)
@@ -1,2 +1,2 @@
1
1
  require 'ransack/helpers/form_builder'
2
- require 'ransack/helpers/form_helper'
2
+ require 'ransack/helpers/form_helper'
@@ -0,0 +1,70 @@
1
+ sv:
2
+ ransack:
3
+ search: "sök"
4
+ predicate: "predikat"
5
+ and: "och"
6
+ or: "eller"
7
+ any: "vilken som"
8
+ all: "alla"
9
+ combinator: "kombinator"
10
+ attribute: "attribut"
11
+ value: "värde"
12
+ condition: "villkor"
13
+ sort: "sortera"
14
+ asc: "stigande"
15
+ desc: "fallande"
16
+ predicates:
17
+ eq: "lika med"
18
+ eq_any: "lika med vilket som"
19
+ eq_all: "lika med alla"
20
+ not_eq: "inte lika med"
21
+ not_eq_any: "inte lika med någon"
22
+ not_eq_all: "inte lika med alla"
23
+ matches: "matchar"
24
+ matches_any: "matchar någon"
25
+ matches_all: "matchar alla"
26
+ does_not_match: "matchar inte"
27
+ does_not_match_any: "matchar inte någon"
28
+ does_not_match_all: "matchar inte alla"
29
+ lt: "mindre än"
30
+ lt_any: "mindre än någon"
31
+ lt_all: "mindre än alla"
32
+ lteq: "mindre än eller lika med"
33
+ lteq_any: "mindre än eller lika med någon"
34
+ lteq_all: "mindre än eller lika med alla"
35
+ gt: "större än"
36
+ gt_any: "större än någon"
37
+ gt_all: "större än alla"
38
+ gteq: "större än eller lika med"
39
+ gteq_any: "större än eller lika med någon"
40
+ gteq_all: "större än eller lika med alla"
41
+ in: "i"
42
+ in_any: "i någon"
43
+ in_all: "i alla"
44
+ not_in: "inte i"
45
+ not_in_any: "inte i någon"
46
+ not_in_all: "inte i alla"
47
+ cont: "innehåller"
48
+ cont_any: "innehåller någon"
49
+ cont_all: "innehåller alla"
50
+ not_cont: "innehåller inte"
51
+ not_cont_any: "innehåller inte någon"
52
+ not_cont_all: "innehåller inte alla"
53
+ start: "börjar med"
54
+ start_any: "börjar med någon"
55
+ start_all: "börjar med alla"
56
+ not_start: "börjar inte med"
57
+ not_start_any: "börjar inte med någon"
58
+ not_start_all: "börjar inte med alla"
59
+ end: "slutar med"
60
+ end_any: "slutar med någon"
61
+ end_all: "slutar med alla"
62
+ not_end: "slutar inte med"
63
+ not_end_any: "slutar inte med någon"
64
+ not_end_all: "slutar inte med alla"
65
+ 'true': "är sant"
66
+ 'false': "är falskt"
67
+ present: "existerar"
68
+ blank: "är tom"
69
+ 'null': "är null"
70
+ not_null: "är inte null"
@@ -30,7 +30,7 @@ module Ransack
30
30
 
31
31
  def type
32
32
  if ransacker
33
- return ransacker.type
33
+ ransacker.type
34
34
  else
35
35
  context.type_for(self)
36
36
  end
@@ -127,7 +127,6 @@ module Ransack
127
127
  alias :m= :combinator=
128
128
  alias :m :combinator
129
129
 
130
-
131
130
  # == build_attribute
132
131
  #
133
132
  # This method was originally called from Nodes::Grouping#new_condition
@@ -263,7 +262,6 @@ module Ransack
263
262
  attr.attr
264
263
  end
265
264
 
266
-
267
265
  def default_type
268
266
  predicate.type || (attributes.first && attributes.first.type)
269
267
  end
@@ -108,7 +108,7 @@ module Ransack
108
108
  alias :g= :groupings=
109
109
 
110
110
  def method_missing(method_id, *args)
111
- method_name = method_id.to_s
111
+ method_name = method_id.to_s.dup
112
112
  writer = method_name.sub!(/\=$/, ''.freeze)
113
113
  if attribute_method?(method_name)
114
114
  if writer
@@ -9,7 +9,7 @@ module Ransack
9
9
  class << self
10
10
  def extract(context, str)
11
11
  return unless str
12
- attr, direction = str.split(/\s+/,2)
12
+ attr, direction = str.split(/\s+/, 2)
13
13
  self.new(context).build(name: attr, dir: direction)
14
14
  end
15
15
  end
@@ -31,8 +31,8 @@ module Ransack
31
31
  end
32
32
 
33
33
  def name=(name)
34
- @name = name
35
- context.bind(self, name)
34
+ @name = context.ransackable_alias(name) || name
35
+ context.bind(self, @name)
36
36
  end
37
37
 
38
38
  def dir=(dir)
@@ -50,7 +50,7 @@ module Ransack
50
50
  y, m, d = *[val].flatten
51
51
  m ||= 1
52
52
  d ||= 1
53
- Date.new(y,m,d) rescue nil
53
+ Date.new(y, m, d) rescue nil
54
54
  end
55
55
  end
56
56
 
@@ -15,9 +15,11 @@ module Ransack
15
15
  :translate, :to => :base
16
16
 
17
17
  def initialize(object, params = {}, options = {})
18
+ strip_whitespace = options.fetch(:strip_whitespace, Ransack.options[:strip_whitespace])
18
19
  params = params.to_unsafe_h if params.respond_to?(:to_unsafe_h)
19
20
  if params.is_a? Hash
20
21
  params = params.dup
22
+ params = params.transform_values { |v| v.is_a?(String) && strip_whitespace ? v.strip : v }
21
23
  params.delete_if { |k, v| [*v].all?{ |i| i.blank? && i != false } }
22
24
  else
23
25
  params = {}
@@ -29,6 +31,7 @@ module Ransack
29
31
  )
30
32
  @scope_args = {}
31
33
  @sorts ||= []
34
+ @ignore_unknown_conditions = options[:ignore_unknown_conditions] == false ? false : true
32
35
  build(params.with_indifferent_access)
33
36
  end
34
37
 
@@ -44,7 +47,7 @@ module Ransack
44
47
  base.send("#{key}=", value)
45
48
  elsif @context.ransackable_scope?(key, @context.object)
46
49
  add_scope(key, value)
47
- elsif !Ransack.options[:ignore_unknown_conditions]
50
+ elsif !Ransack.options[:ignore_unknown_conditions] || !@ignore_unknown_conditions
48
51
  raise ArgumentError, "Invalid search term #{key}"
49
52
  end
50
53
  end
@@ -32,6 +32,7 @@ module Ransack
32
32
  defaults = base_ancestors.map do |klass|
33
33
  "ransack.attributes.#{i18n_key(klass)}.#{original_name}".to_sym
34
34
  end
35
+ defaults << options.delete(:default) if options[:default]
35
36
 
36
37
  translated_names = attribute_names.map do |name|
37
38
  attribute_name(context, name, options[:include_associations])
@@ -48,9 +49,8 @@ module Ransack
48
49
  defaults << "%{attributes}".freeze
49
50
  end
50
51
 
51
- defaults << options.delete(:default) if options[:default]
52
52
  options.reverse_merge! count: 1, default: defaults
53
- I18n.translate(defaults.shift, options.merge(interpolations))
53
+ I18n.translate(defaults.shift, **options.merge(interpolations))
54
54
  end
55
55
 
56
56
  def association(key, options = {})
@@ -67,7 +67,7 @@ module Ransack
67
67
  end
68
68
  defaults << context.traverse(key).model_name.human
69
69
  options = { :count => 1, :default => defaults }
70
- I18n.translate(defaults.shift, options)
70
+ I18n.translate(defaults.shift, **options)
71
71
  end
72
72
 
73
73
  private
@@ -83,7 +83,7 @@ module Ransack
83
83
  options = { count: 1, default: defaults }
84
84
  interpolations = build_interpolations(associated_class)
85
85
 
86
- I18n.translate(defaults.shift, options.merge(interpolations))
86
+ I18n.translate(defaults.shift, **options.merge(interpolations))
87
87
  end
88
88
 
89
89
  def default_attribute_name
@@ -1,3 +1,3 @@
1
1
  module Ransack
2
- VERSION = '2.3.2'
2
+ VERSION = '2.5.0'
3
3
  end
data/lib/ransack.rb CHANGED
@@ -1,13 +1,13 @@
1
1
  require 'active_support/core_ext'
2
2
  require 'ransack/configuration'
3
3
  require 'ransack/adapters'
4
- require 'polyamorous'
4
+ require 'polyamorous/polyamorous'
5
5
 
6
6
  Ransack::Adapters.object_mapper.require_constants
7
7
 
8
8
  module Ransack
9
9
  extend Configuration
10
- class UntraversableAssociationError < StandardError; end;
10
+ class UntraversableAssociationError < StandardError; end
11
11
  end
12
12
 
13
13
  Ransack.configure do |config|
data/ransack.gemspec CHANGED
@@ -1,4 +1,5 @@
1
1
  # -*- encoding: utf-8 -*-
2
+
2
3
  $:.push File.expand_path("../lib", __FILE__)
3
4
  require "ransack/version"
4
5
 
@@ -6,27 +7,20 @@ Gem::Specification.new do |s|
6
7
  s.name = "ransack"
7
8
  s.version = Ransack::VERSION
8
9
  s.platform = Gem::Platform::RUBY
9
- s.authors = ["Ernie Miller", "Ryan Bigg", "Jon Atack","Sean Carroll"]
10
- s.email = ["ernie@erniemiller.org", "radarlistener@gmail.com", "jonnyatack@gmail.com","sfcarroll@gmail.com"]
10
+ s.authors = ["Ernie Miller", "Ryan Bigg", "Jon Atack", "Sean Carroll"]
11
+ s.email = ["ernie@erniemiller.org", "radarlistener@gmail.com", "jonnyatack@gmail.com", "sfcarroll@gmail.com"]
11
12
  s.homepage = "https://github.com/activerecord-hackery/ransack"
12
13
  s.summary = %q{Object-based searching for Active Record and Mongoid (currently).}
13
14
  s.description = %q{Ransack is the successor to the MetaSearch gem. It improves and expands upon MetaSearch's functionality, but does not have a 100%-compatible API.}
14
- s.required_ruby_version = '>= 2.3'
15
+ s.required_ruby_version = '>= 2.6'
15
16
  s.license = 'MIT'
16
17
 
17
- s.add_dependency 'activerecord', '>= 5.2.1'
18
- s.add_dependency 'activesupport', '>= 5.2.1'
18
+ s.add_dependency 'activerecord', '>= 5.2.4'
19
+ s.add_dependency 'activesupport', '>= 5.2.4'
19
20
  s.add_dependency 'i18n'
20
- s.add_dependency 'polyamorous', Ransack::VERSION.to_s
21
21
 
22
22
  s.files = `git ls-files`.split("\n")
23
-
24
- s.test_files = `git ls-files -- {test,spec,features}/*`
25
- .split("\n")
26
-
27
- s.executables = `git ls-files -- bin/*`
28
- .split("\n")
29
- .map { |f| File.basename(f) }
30
-
23
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
24
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
31
25
  s.require_paths = ["lib"]
32
26
  end
@@ -2,4 +2,4 @@ Article.blueprint do
2
2
  person
3
3
  title
4
4
  body
5
- end
5
+ end
@@ -2,4 +2,4 @@ Comment.blueprint do
2
2
  article
3
3
  person
4
4
  body
5
- end
5
+ end
@@ -2,4 +2,4 @@ Note.blueprint do
2
2
  note
3
3
  notable_type { "Article" }
4
4
  notable_id
5
- end
5
+ end
@@ -1,3 +1,3 @@
1
1
  Tag.blueprint do
2
2
  name { Sham.tag_name }
3
- end
3
+ end
data/spec/console.rb CHANGED
@@ -14,11 +14,11 @@ Sham.define do
14
14
  title { Faker::Lorem.sentence }
15
15
  body { Faker::Lorem.paragraph }
16
16
  salary { |index| 30000 + (index * 1000) }
17
- tag_name { Faker::Lorem.words(3).join(' ') }
18
- note { Faker::Lorem.words(7).join(' ') }
19
- only_admin { Faker::Lorem.words(3).join(' ') }
20
- only_search { Faker::Lorem.words(3).join(' ') }
21
- only_sort { Faker::Lorem.words(3).join(' ') }
17
+ tag_name { Faker::Lorem.words(number: 3).join(' ') }
18
+ note { Faker::Lorem.words(number: 7).join(' ') }
19
+ only_admin { Faker::Lorem.words(number: 3).join(' ') }
20
+ only_search { Faker::Lorem.words(number: 3).join(' ') }
21
+ only_sort { Faker::Lorem.words(number: 3).join(' ') }
22
22
  notable_id { |id| id }
23
23
  end
24
24
 
@@ -6,4 +6,4 @@ module RansackHelper
6
6
  def quote_column_name(column)
7
7
  ActiveRecord::Base.connection.quote_column_name(column)
8
8
  end
9
- end
9
+ end
@@ -10,7 +10,14 @@ module Polyamorous
10
10
  new_join_association(reflection, parent.children, Article)
11
11
  }
12
12
 
13
- it 'leaves the orginal reflection intact for thread safety' do
13
+ subject { new_join_association(reflection, parent.children, Person) }
14
+
15
+ it 'respects polymorphism on equality test' do
16
+ expect(subject).to eq new_join_association(reflection, parent.children, Person)
17
+ expect(subject).not_to eq new_join_association(reflection, parent.children, Article)
18
+ end
19
+
20
+ it 'leaves the original reflection intact for thread safety' do
14
21
  reflection.instance_variable_set(:@klass, Article)
15
22
  join_association
16
23
  .swapping_reflection_klass(reflection, Person) do |new_reflection|
File without changes