ransack 1.7.0 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +2 -0
  3. data/.travis.yml +16 -48
  4. data/CHANGELOG.md +409 -26
  5. data/CONTRIBUTING.md +48 -20
  6. data/Gemfile +9 -13
  7. data/README.md +352 -92
  8. data/Rakefile +6 -25
  9. data/lib/polyamorous/activerecord_5.0_ruby_2/join_association.rb +2 -0
  10. data/lib/polyamorous/activerecord_5.0_ruby_2/join_dependency.rb +2 -0
  11. data/lib/polyamorous/activerecord_5.1_ruby_2/join_association.rb +32 -0
  12. data/lib/polyamorous/activerecord_5.1_ruby_2/join_dependency.rb +112 -0
  13. data/lib/polyamorous/activerecord_5.2.0_ruby_2/join_association.rb +32 -0
  14. data/lib/polyamorous/activerecord_5.2.0_ruby_2/join_dependency.rb +113 -0
  15. data/lib/polyamorous/activerecord_5.2.1_ruby_2/join_association.rb +31 -0
  16. data/lib/polyamorous/activerecord_5.2.1_ruby_2/join_dependency.rb +57 -0
  17. data/lib/polyamorous/join.rb +70 -0
  18. data/lib/polyamorous/swapping_reflection_class.rb +11 -0
  19. data/lib/polyamorous/tree_node.rb +7 -0
  20. data/lib/polyamorous.rb +25 -0
  21. data/lib/ransack/adapters/active_record/base.rb +23 -2
  22. data/lib/ransack/adapters/active_record/context.rb +210 -135
  23. data/lib/ransack/adapters/active_record/ransack/constants.rb +53 -53
  24. data/lib/ransack/adapters/active_record/ransack/context.rb +11 -15
  25. data/lib/ransack/adapters/active_record/ransack/nodes/condition.rb +33 -30
  26. data/lib/ransack/adapters/active_record/ransack/translate.rb +1 -5
  27. data/lib/ransack/adapters/active_record/ransack/visitor.rb +23 -0
  28. data/lib/ransack/adapters/active_record.rb +11 -10
  29. data/lib/ransack/adapters.rb +45 -23
  30. data/lib/ransack/configuration.rb +91 -4
  31. data/lib/ransack/constants.rb +14 -26
  32. data/lib/ransack/context.rb +29 -18
  33. data/lib/ransack/helpers/form_builder.rb +27 -12
  34. data/lib/ransack/helpers/form_helper.rb +75 -70
  35. data/lib/ransack/locale/ar.yml +70 -0
  36. data/lib/ransack/locale/az.yml +70 -0
  37. data/lib/ransack/locale/bg.yml +70 -0
  38. data/lib/ransack/locale/da.yml +70 -0
  39. data/lib/ransack/locale/el.yml +70 -0
  40. data/lib/ransack/locale/id.yml +70 -0
  41. data/lib/ransack/locale/it.yml +70 -0
  42. data/lib/ransack/locale/ja.yml +70 -0
  43. data/lib/ransack/locale/nl.yml +4 -4
  44. data/lib/ransack/locale/pt-BR.yml +70 -0
  45. data/lib/ransack/locale/ru.yml +70 -0
  46. data/lib/ransack/locale/tr.yml +70 -0
  47. data/lib/ransack/locale/{zh.yml → zh-CN.yml} +13 -13
  48. data/lib/ransack/locale/zh-TW.yml +70 -0
  49. data/lib/ransack/nodes/attribute.rb +5 -2
  50. data/lib/ransack/nodes/bindable.rb +18 -6
  51. data/lib/ransack/nodes/condition.rb +77 -28
  52. data/lib/ransack/nodes/grouping.rb +16 -10
  53. data/lib/ransack/nodes/sort.rb +9 -5
  54. data/lib/ransack/nodes/value.rb +74 -68
  55. data/lib/ransack/nodes.rb +1 -1
  56. data/lib/ransack/predicate.rb +15 -19
  57. data/lib/ransack/search.rb +14 -7
  58. data/lib/ransack/translate.rb +3 -3
  59. data/lib/ransack/version.rb +1 -1
  60. data/lib/ransack/visitor.rb +1 -12
  61. data/lib/ransack.rb +7 -7
  62. data/logo/ransack-h.png +0 -0
  63. data/logo/ransack-h.svg +34 -0
  64. data/logo/ransack-v.png +0 -0
  65. data/logo/ransack-v.svg +34 -0
  66. data/logo/ransack.png +0 -0
  67. data/logo/ransack.svg +21 -0
  68. data/ransack.gemspec +9 -10
  69. data/spec/console.rb +4 -0
  70. data/spec/helpers/polyamorous_helper.rb +24 -0
  71. data/spec/ransack/adapters/active_record/base_spec.rb +365 -74
  72. data/spec/ransack/adapters/active_record/context_spec.rb +14 -19
  73. data/spec/ransack/configuration_spec.rb +87 -14
  74. data/spec/ransack/helpers/form_builder_spec.rb +2 -11
  75. data/spec/ransack/helpers/form_helper_spec.rb +481 -113
  76. data/spec/ransack/join_association_spec.rb +28 -0
  77. data/spec/ransack/join_dependency_spec.rb +86 -0
  78. data/spec/ransack/join_spec.rb +19 -0
  79. data/spec/ransack/nodes/condition_spec.rb +24 -0
  80. data/spec/ransack/nodes/grouping_spec.rb +56 -0
  81. data/spec/ransack/predicate_spec.rb +27 -5
  82. data/spec/ransack/search_spec.rb +84 -70
  83. data/spec/spec_helper.rb +4 -0
  84. data/spec/support/schema.rb +86 -41
  85. metadata +60 -81
  86. data/lib/ransack/adapters/active_record/3.0/compat.rb +0 -179
  87. data/lib/ransack/adapters/active_record/3.0/context.rb +0 -201
  88. data/lib/ransack/adapters/active_record/3.1/context.rb +0 -215
  89. data/lib/ransack/adapters/active_record/3.2/context.rb +0 -44
  90. data/lib/ransack/adapters/active_record/compat.rb +0 -14
  91. data/lib/ransack/adapters/mongoid/3.2/.gitkeep +0 -0
  92. data/lib/ransack/adapters/mongoid/attributes/attribute.rb +0 -37
  93. data/lib/ransack/adapters/mongoid/attributes/order_predications.rb +0 -17
  94. data/lib/ransack/adapters/mongoid/attributes/predications.rb +0 -141
  95. data/lib/ransack/adapters/mongoid/base.rb +0 -130
  96. data/lib/ransack/adapters/mongoid/context.rb +0 -208
  97. data/lib/ransack/adapters/mongoid/inquiry_hash.rb +0 -23
  98. data/lib/ransack/adapters/mongoid/ransack/constants.rb +0 -88
  99. data/lib/ransack/adapters/mongoid/ransack/context.rb +0 -60
  100. data/lib/ransack/adapters/mongoid/ransack/nodes/condition.rb +0 -27
  101. data/lib/ransack/adapters/mongoid/ransack/translate.rb +0 -13
  102. data/lib/ransack/adapters/mongoid/ransack/visitor.rb +0 -24
  103. data/lib/ransack/adapters/mongoid/table.rb +0 -35
  104. data/lib/ransack/adapters/mongoid.rb +0 -13
  105. data/spec/mongoid/adapters/mongoid/base_spec.rb +0 -276
  106. data/spec/mongoid/adapters/mongoid/context_spec.rb +0 -56
  107. data/spec/mongoid/configuration_spec.rb +0 -102
  108. data/spec/mongoid/dependencies_spec.rb +0 -8
  109. data/spec/mongoid/helpers/ransack_helper.rb +0 -11
  110. data/spec/mongoid/nodes/condition_spec.rb +0 -34
  111. data/spec/mongoid/nodes/grouping_spec.rb +0 -13
  112. data/spec/mongoid/predicate_spec.rb +0 -155
  113. data/spec/mongoid/search_spec.rb +0 -446
  114. data/spec/mongoid/support/mongoid.yml +0 -6
  115. data/spec/mongoid/support/schema.rb +0 -128
  116. data/spec/mongoid/translate_spec.rb +0 -14
  117. data/spec/mongoid_spec_helper.rb +0 -59
  118. data/spec/ransack/dependencies_spec.rb +0 -12
@@ -9,9 +9,10 @@ module Ransack
9
9
 
10
10
  class << self
11
11
  def extract(context, key, values)
12
- attributes, predicate = extract_attributes_and_predicate(key, context)
12
+ attributes, predicate, combinator =
13
+ extract_values_for_condition(key, context)
14
+
13
15
  if attributes.size > 0 && predicate
14
- combinator = key.match(/_(or|and)_/) ? $1 : nil
15
16
  condition = self.new(context)
16
17
  condition.build(
17
18
  :a => attributes,
@@ -31,20 +32,34 @@ module Ransack
31
32
 
32
33
  private
33
34
 
34
- def extract_attributes_and_predicate(key, context = nil)
35
- str = key.dup
36
- name = Predicate.detect_and_strip_from_string!(str)
37
- predicate = Predicate.named(name)
38
- unless predicate || Ransack.options[:ignore_unknown_conditions]
39
- raise ArgumentError, "No valid predicate for #{key}"
40
- end
41
- if context.present? && context.attribute_method?(str)
42
- attributes = [str]
43
- else
44
- attributes = str.split(/_and_|_or_/)
35
+ def extract_values_for_condition(key, context = nil)
36
+ str = key.dup
37
+ name = Predicate.detect_and_strip_from_string!(str)
38
+ predicate = Predicate.named(name)
39
+
40
+ unless predicate || Ransack.options[:ignore_unknown_conditions]
41
+ raise ArgumentError, "No valid predicate for #{key}"
42
+ end
43
+
44
+ if context.present?
45
+ str = context.ransackable_alias(str)
46
+ end
47
+
48
+ combinator =
49
+ if str.match(/_(or|and)_/)
50
+ $1
51
+ else
52
+ nil
53
+ end
54
+
55
+ if context.present? && context.attribute_method?(str)
56
+ attributes = [str]
57
+ else
58
+ attributes = str.split(/_and_|_or_/)
59
+ end
60
+
61
+ [attributes, predicate, combinator]
45
62
  end
46
- [attributes, predicate]
47
- end
48
63
  end
49
64
 
50
65
  def valid?
@@ -64,14 +79,12 @@ module Ransack
64
79
  def attributes=(args)
65
80
  case args
66
81
  when Array
67
- args.each do |attr|
68
- attr = Attribute.new(@context, attr)
69
- self.attributes << attr if attr.valid?
82
+ args.each do |name|
83
+ build_attribute(name)
70
84
  end
71
85
  when Hash
72
86
  args.each do |index, attrs|
73
- attr = Attribute.new(@context, attrs[:name], attrs[:ransacker_args])
74
- self.attributes << attr if attr.valid?
87
+ build_attribute(attrs[:name], attrs[:ransacker_args])
75
88
  end
76
89
  else
77
90
  raise ArgumentError,
@@ -114,9 +127,32 @@ module Ransack
114
127
  alias :m= :combinator=
115
128
  alias :m :combinator
116
129
 
117
- def build_attribute(name = nil)
118
- Attribute.new(@context, name).tap do |attribute|
119
- self.attributes << attribute
130
+
131
+ # == build_attribute
132
+ #
133
+ # This method was originally called from Nodes::Grouping#new_condition
134
+ # only, without arguments, without #valid? checking, to build a new
135
+ # grouping condition.
136
+ #
137
+ # After refactoring in 235eae3, it is now called from 2 places:
138
+ #
139
+ # 1. Nodes::Condition#attributes=, with +name+ argument passed or +name+
140
+ # and +ransacker_args+. Attributes are included only if #valid?.
141
+ #
142
+ # 2. Nodes::Grouping#new_condition without arguments. In this case, the
143
+ # #valid? conditional needs to be bypassed, otherwise nothing is
144
+ # built. The `name.nil?` conditional below currently does this.
145
+ #
146
+ # TODO: Add test coverage for this behavior and ensure that `name.nil?`
147
+ # isn't fixing issue #701 by introducing untested regressions.
148
+ #
149
+ def build_attribute(name = nil, ransacker_args = [])
150
+ Attribute.new(@context, name, ransacker_args).tap do |attribute|
151
+ @context.bind(attribute, attribute.name)
152
+ self.attributes << attribute if name.nil? || attribute.valid?
153
+ if predicate && !negative?
154
+ @context.lock_association(attribute.parent)
155
+ end
120
156
  end
121
157
  end
122
158
 
@@ -168,6 +204,10 @@ module Ransack
168
204
 
169
205
  def predicate_name=(name)
170
206
  self.predicate = Predicate.named(name)
207
+ unless negative?
208
+ attributes.each { |a| context.lock_association(a.parent) }
209
+ end
210
+ @predicate
171
211
  end
172
212
  alias :p= :predicate_name=
173
213
 
@@ -196,15 +236,20 @@ module Ransack
196
236
  val = predicate.format(val)
197
237
  val
198
238
  end
199
- predicate.wants_array ? formatted : formatted.first
239
+ if predicate.wants_array
240
+ formatted
241
+ else
242
+ formatted.first
243
+ end
200
244
  end
201
245
 
202
246
  def arel_predicate_for_attribute(attr)
203
247
  if predicate.arel_predicate === Proc
204
248
  values = casted_values_for_attribute(attr)
205
- predicate.arel_predicate.call(
206
- predicate.wants_array ? values : values.first
207
- )
249
+ unless predicate.wants_array
250
+ values = values.first
251
+ end
252
+ predicate.arel_predicate.call(values)
208
253
  else
209
254
  predicate.arel_predicate
210
255
  end
@@ -224,10 +269,14 @@ module Ransack
224
269
  ]
225
270
  .reject { |e| e[1].blank? }
226
271
  .map { |v| "#{v[0]}: #{v[1]}" }
227
- .join(Constants::COMMA_SPACE)
272
+ .join(', '.freeze)
228
273
  "Condition <#{data}>"
229
274
  end
230
275
 
276
+ def negative?
277
+ predicate.negative?
278
+ end
279
+
231
280
  private
232
281
 
233
282
  def valid_combinator?
@@ -44,16 +44,12 @@ module Ransack
44
44
  self.conditions << condition if condition.valid?
45
45
  end
46
46
  end
47
- self.conditions.uniq!
47
+ remove_duplicate_conditions!
48
48
  end
49
49
  alias :c= :conditions=
50
50
 
51
51
  def [](key)
52
- if condition = conditions.detect { |c| c.key == key.to_s }
53
- condition
54
- else
55
- nil
56
- end
52
+ conditions.detect { |c| c.key == key.to_s }
57
53
  end
58
54
 
59
55
  def []=(key, value)
@@ -68,7 +64,6 @@ module Ransack
68
64
  def respond_to?(method_id)
69
65
  super or begin
70
66
  method_name = method_id.to_s
71
- writer = method_name.sub!(/\=$/, Constants::EMPTY)
72
67
  attribute_method?(method_name) ? true : false
73
68
  end
74
69
  end
@@ -114,7 +109,7 @@ module Ransack
114
109
 
115
110
  def method_missing(method_id, *args)
116
111
  method_name = method_id.to_s
117
- writer = method_name.sub!(/\=$/, Constants::EMPTY)
112
+ writer = method_name.sub!(/\=$/, ''.freeze)
118
113
  if attribute_method?(method_name)
119
114
  if writer
120
115
  write_attribute(method_name, *args)
@@ -169,7 +164,7 @@ module Ransack
169
164
  ]
170
165
  .reject { |e| e[1].blank? }
171
166
  .map { |v| "#{v[0]}: #{v[1]}" }
172
- .join(Constants::COMMA_SPACE)
167
+ .join(', '.freeze)
173
168
  "Grouping <#{data}>"
174
169
  end
175
170
 
@@ -191,10 +186,21 @@ module Ransack
191
186
  end
192
187
 
193
188
  def strip_predicate_and_index(str)
194
- string = str.split(/\(/).first
189
+ string = str[/(.+?)\(/, 1] || str.dup
195
190
  Predicate.detect_and_strip_from_string!(string)
196
191
  string
197
192
  end
193
+
194
+ def remove_duplicate_conditions!
195
+ # If self.conditions.uniq! is called without passing a block, then
196
+ # conditions differing only by ransacker_args within attributes are
197
+ # wrongly considered equal and are removed.
198
+ self.conditions.uniq! do |c|
199
+ c.attributes.map { |a| [a.name, a.ransacker_args] }.flatten +
200
+ [c.predicate.name] +
201
+ c.values.map { |v| v.value }
202
+ end
203
+ end
198
204
  end
199
205
  end
200
206
  end
@@ -3,7 +3,7 @@ module Ransack
3
3
  class Sort < Node
4
4
  include Bindable
5
5
 
6
- attr_reader :name, :dir
6
+ attr_reader :name, :dir, :ransacker_args
7
7
  i18n_word :asc, :desc
8
8
 
9
9
  class << self
@@ -16,7 +16,7 @@ module Ransack
16
16
 
17
17
  def build(params)
18
18
  params.with_indifferent_access.each do |key, value|
19
- if key.match(/^(name|dir)$/)
19
+ if key.match(/^(name|dir|ransacker_args)$/)
20
20
  self.send("#{key}=", value)
21
21
  end
22
22
  end
@@ -32,19 +32,23 @@ module Ransack
32
32
 
33
33
  def name=(name)
34
34
  @name = name
35
- context.bind(self, name) unless name.blank?
35
+ context.bind(self, name)
36
36
  end
37
37
 
38
38
  def dir=(dir)
39
39
  dir = dir.downcase if dir
40
40
  @dir =
41
- if Constants::ASC_DESC.include?(dir)
41
+ if dir == 'asc'.freeze || dir == 'desc'.freeze
42
42
  dir
43
43
  else
44
- Constants::ASC
44
+ 'asc'.freeze
45
45
  end
46
46
  end
47
47
 
48
+ def ransacker_args=(ransack_args)
49
+ @ransacker_args = ransack_args
50
+ end
51
+
48
52
  end
49
53
  end
50
54
  end
@@ -23,87 +23,93 @@ module Ransack
23
23
  end
24
24
 
25
25
  def cast(type)
26
- case type
27
- when :date
28
- cast_to_date(value)
29
- when :datetime, :timestamp, :time
30
- cast_to_time(value)
31
- when :boolean
32
- cast_to_boolean(value)
33
- when :integer
34
- cast_to_integer(value)
35
- when :float
36
- cast_to_float(value)
37
- when :decimal
38
- cast_to_decimal(value)
39
- else
40
- cast_to_string(value)
41
- end
42
- end
26
+ case type
27
+ when :date
28
+ cast_to_date(value)
29
+ when :datetime, :timestamp, :time
30
+ cast_to_time(value)
31
+ when :boolean
32
+ cast_to_boolean(value)
33
+ when :integer
34
+ cast_to_integer(value)
35
+ when :float
36
+ cast_to_float(value)
37
+ when :decimal
38
+ cast_to_decimal(value)
39
+ when :money
40
+ cast_to_money(value)
41
+ else
42
+ cast_to_string(value)
43
+ end
44
+ end
43
45
 
44
- def cast_to_date(val)
45
- if val.respond_to?(:to_date)
46
- val.to_date rescue nil
47
- else
48
- y, m, d = *[val].flatten
49
- m ||= 1
50
- d ||= 1
51
- Date.new(y,m,d) rescue nil
52
- end
53
- end
46
+ def cast_to_date(val)
47
+ if val.respond_to?(:to_date)
48
+ val.to_date rescue nil
49
+ else
50
+ y, m, d = *[val].flatten
51
+ m ||= 1
52
+ d ||= 1
53
+ Date.new(y,m,d) rescue nil
54
+ end
55
+ end
54
56
 
55
- def cast_to_time(val)
56
- if val.is_a?(Array)
57
- Time.zone.local(*val) rescue nil
58
- else
59
- unless val.acts_like?(:time)
60
- val = val.is_a?(String) ? Time.zone.parse(val) : val.to_time rescue val
61
- end
62
- val.in_time_zone rescue nil
63
- end
64
- end
57
+ def cast_to_time(val)
58
+ if val.is_a?(Array)
59
+ Time.zone.local(*val) rescue nil
60
+ else
61
+ unless val.acts_like?(:time)
62
+ val = val.is_a?(String) ? Time.zone.parse(val) : val.to_time rescue val
63
+ end
64
+ val.in_time_zone rescue nil
65
+ end
66
+ end
65
67
 
66
- def cast_to_boolean(val)
67
- if Constants::TRUE_VALUES.include?(val)
68
- true
69
- elsif Constants::FALSE_VALUES.include?(val)
70
- false
71
- else
72
- nil
73
- end
74
- end
68
+ def cast_to_boolean(val)
69
+ if Constants::TRUE_VALUES.include?(val)
70
+ true
71
+ elsif Constants::FALSE_VALUES.include?(val)
72
+ false
73
+ else
74
+ nil
75
+ end
76
+ end
75
77
 
76
- def cast_to_string(val)
77
- val.respond_to?(:to_s) ? val.to_s : String.new(val)
78
- end
78
+ def cast_to_string(val)
79
+ val.respond_to?(:to_s) ? val.to_s : String.new(val)
80
+ end
79
81
 
80
- def cast_to_integer(val)
81
- val.blank? ? nil : val.to_i
82
- end
82
+ def cast_to_integer(val)
83
+ val.blank? ? nil : val.to_i
84
+ end
83
85
 
84
- def cast_to_float(val)
85
- val.blank? ? nil : val.to_f
86
- end
86
+ def cast_to_float(val)
87
+ val.blank? ? nil : val.to_f
88
+ end
87
89
 
88
- def cast_to_decimal(val)
89
- if val.blank?
90
- nil
91
- elsif val.class == BigDecimal
92
- val
93
- elsif val.respond_to?(:to_d)
94
- val.to_d
95
- else
96
- val.to_s.to_d
97
- end
90
+ def cast_to_decimal(val)
91
+ if val.blank?
92
+ nil
93
+ elsif val.class == BigDecimal
94
+ val
95
+ elsif val.respond_to?(:to_d)
96
+ val.to_d
97
+ else
98
+ val.to_s.to_d
98
99
  end
100
+ end
101
+
102
+ def cast_to_money(val)
103
+ val.blank? ? nil : val.to_f.to_s
104
+ end
99
105
 
100
106
  def inspect
101
107
  "Value <#{value}>"
102
108
  end
103
109
 
104
- def array_of_arrays?(val)
105
- Array === val && Array === val.first
106
- end
110
+ def array_of_arrays?(val)
111
+ Array === val && Array === val.first
112
+ end
107
113
  end
108
114
  end
109
115
  end
data/lib/ransack/nodes.rb CHANGED
@@ -3,6 +3,6 @@ require 'ransack/nodes/node'
3
3
  require 'ransack/nodes/attribute'
4
4
  require 'ransack/nodes/value'
5
5
  require 'ransack/nodes/condition'
6
- Ransack::Adapters.require_nodes
6
+ Ransack::Adapters.object_mapper.require_nodes
7
7
  require 'ransack/nodes/sort'
8
8
  require 'ransack/nodes/grouping'
@@ -9,34 +9,26 @@ module Ransack
9
9
  Ransack.predicates.keys
10
10
  end
11
11
 
12
- def names_by_decreasing_length
13
- names.sort { |a,b| b.length <=> a.length }
14
- end
15
-
16
12
  def named(name)
17
13
  Ransack.predicates[name.to_s]
18
14
  end
19
15
 
20
16
  def detect_and_strip_from_string!(str)
21
- if p = detect_from_string(str)
22
- str.sub! /_#{p}$/, Constants::EMPTY
23
- p
24
- end
17
+ detect_from_string str, chomp: true
25
18
  end
26
19
 
27
- def detect_from_string(str)
28
- names_by_decreasing_length.detect { |p| str.end_with?("_#{p}") }
29
- end
20
+ def detect_from_string(str, chomp: false)
21
+ return unless str
30
22
 
31
- # def name_from_attribute_name(attribute_name)
32
- # names_by_decreasing_length.detect {
33
- # |p| attribute_name.to_s.match(/_#{p}$/)
34
- # }
35
- # end
23
+ Ransack.predicates.sorted_names_with_underscores.each do |predicate, underscored|
24
+ if str.end_with? underscored
25
+ str.chomp! underscored if chomp
26
+ return predicate
27
+ end
28
+ end
36
29
 
37
- # def for_attribute_name(attribute_name)
38
- # self.named(detect_from_string(attribute_name.to_s))
39
- # end
30
+ nil
31
+ end
40
32
 
41
33
  end
42
34
 
@@ -74,5 +66,9 @@ module Ransack
74
66
  vals.any? { |v| validator.call(type ? v.cast(type) : v.value) }
75
67
  end
76
68
 
69
+ def negative?
70
+ @name.include?("not_".freeze)
71
+ end
72
+
77
73
  end
78
74
  end
@@ -1,6 +1,6 @@
1
1
  require 'ransack/nodes'
2
2
  require 'ransack/context'
3
- Ransack::Adapters.require_search
3
+ Ransack::Adapters.object_mapper.require_search
4
4
  require 'ransack/naming'
5
5
 
6
6
  module Ransack
@@ -15,6 +15,7 @@ module Ransack
15
15
  :translate, :to => :base
16
16
 
17
17
  def initialize(object, params = {}, options = {})
18
+ params = params.to_unsafe_h if params.respond_to?(:to_unsafe_h)
18
19
  if params.is_a? Hash
19
20
  params = params.dup
20
21
  params.delete_if { |k, v| [*v].all?{ |i| i.blank? && i != false } }
@@ -37,7 +38,7 @@ module Ransack
37
38
 
38
39
  def build(params)
39
40
  collapse_multiparameter_attributes!(params).each do |key, value|
40
- if Constants::S_SORTS.include?(key)
41
+ if ['s'.freeze, 'sorts'.freeze].freeze.include?(key)
41
42
  send("#{key}=", value)
42
43
  elsif base.attribute_method?(key)
43
44
  base.send("#{key}=", value)
@@ -92,7 +93,7 @@ module Ransack
92
93
 
93
94
  def method_missing(method_id, *args)
94
95
  method_name = method_id.to_s
95
- getter_name = method_name.sub(/=$/, Constants::EMPTY)
96
+ getter_name = method_name.sub(/=$/, ''.freeze)
96
97
  if base.attribute_method?(getter_name)
97
98
  base.send(method_id, *args)
98
99
  elsif @context.ransackable_scope?(getter_name, @context.object)
@@ -113,8 +114,8 @@ module Ransack
113
114
  [:base, base.inspect]
114
115
  ]
115
116
  .compact
116
- .map { |d| d.join(Constants::COLON_SPACE) }
117
- .join(Constants::COMMA_SPACE)
117
+ .map { |d| d.join(': '.freeze) }
118
+ .join(', '.freeze)
118
119
 
119
120
  "Ransack::Search<#{details}>"
120
121
  end
@@ -122,12 +123,18 @@ module Ransack
122
123
  private
123
124
 
124
125
  def add_scope(key, args)
126
+ sanitized_args = if Ransack.options[:sanitize_scope_args] && !@context.ransackable_scope_skip_sanitize_args?(key, @context.object)
127
+ sanitized_scope_args(args)
128
+ else
129
+ args
130
+ end
131
+
125
132
  if @context.scope_arity(key) == 1
126
133
  @scope_args[key] = args.is_a?(Array) ? args[0] : args
127
134
  else
128
- @scope_args[key] = args.is_a?(Array) ? sanitized_scope_args(args) : args
135
+ @scope_args[key] = args.is_a?(Array) ? sanitized_args : args
129
136
  end
130
- @context.chain_scope(key, sanitized_scope_args(args))
137
+ @context.chain_scope(key, sanitized_args)
131
138
  end
132
139
 
133
140
  def sanitized_scope_args(args)
@@ -24,8 +24,8 @@ module Ransack
24
24
  base_ancestors = base_class.ancestors.select {
25
25
  |x| x.respond_to?(:model_name)
26
26
  }
27
- predicate = Predicate.detect_from_string(original_name)
28
- attributes_str = original_name.sub(/_#{predicate}$/, Constants::EMPTY)
27
+ attributes_str = original_name.dup # will be modified by ⬇
28
+ predicate = Predicate.detect_and_strip_from_string!(attributes_str)
29
29
  attribute_names = attributes_str.split(/_and_|_or_/)
30
30
  combinator = attributes_str.match(/_and_/) ? :and : :or
31
31
  defaults = base_ancestors.map do |klass|
@@ -74,7 +74,7 @@ module Ransack
74
74
  def self.attribute_name(context, name, include_associations = nil)
75
75
  @context, @name = context, name
76
76
  @assoc_path = context.association_path(name)
77
- @attr_name = @name.sub(/^#{@assoc_path}_/, Constants::EMPTY)
77
+ @attr_name = @name.sub(/^#{@assoc_path}_/, ''.freeze)
78
78
  associated_class = @context.traverse(@assoc_path) if @assoc_path.present?
79
79
  @include_associated = include_associations && associated_class
80
80
 
@@ -1,3 +1,3 @@
1
1
  module Ransack
2
- VERSION = '1.7.0'
2
+ VERSION = '2.1.1'
3
3
  end
@@ -31,17 +31,7 @@ module Ransack
31
31
 
32
32
  def visit_or(object)
33
33
  nodes = object.values.map { |o| accept(o) }.compact
34
- return nil unless nodes.size > 0
35
-
36
- if nodes.size > 1
37
- nodes.inject(&:or)
38
- else
39
- nodes.first
40
- end
41
- end
42
-
43
- def visit_Ransack_Nodes_Sort(object)
44
- object.attr.send(object.dir) if object.valid?
34
+ nodes.inject(&:or)
45
35
  end
46
36
 
47
37
  def quoted?(object)
@@ -57,6 +47,5 @@ module Ransack
57
47
  klass.name.gsub(Constants::TWO_COLONS, Constants::UNDERSCORE)
58
48
  }"
59
49
  end
60
-
61
50
  end
62
51
  end
data/lib/ransack.rb CHANGED
@@ -1,9 +1,8 @@
1
1
  require 'active_support/core_ext'
2
-
3
2
  require 'ransack/configuration'
4
-
5
3
  require 'ransack/adapters'
6
- Ransack::Adapters.require_constants
4
+
5
+ Ransack::Adapters.object_mapper.require_constants
7
6
 
8
7
  module Ransack
9
8
  extend Configuration
@@ -15,7 +14,7 @@ Ransack.configure do |config|
15
14
  config.add_predicate name, :arel_predicate => name
16
15
  end
17
16
  Ransack::Constants::DERIVED_PREDICATES.each do |args|
18
- config.add_predicate *args
17
+ config.add_predicate(*args)
19
18
  end
20
19
  end
21
20
 
@@ -23,9 +22,10 @@ require 'ransack/search'
23
22
  require 'ransack/ransacker'
24
23
  require 'ransack/helpers'
25
24
  require 'action_controller'
26
-
27
25
  require 'ransack/translate'
28
26
 
29
- Ransack::Adapters.require_adapter
27
+ Ransack::Adapters.object_mapper.require_adapter
30
28
 
31
- ActionController::Base.helper Ransack::Helpers::FormHelper
29
+ ActiveSupport.on_load(:action_controller) do
30
+ ActionController::Base.helper Ransack::Helpers::FormHelper
31
+ end
Binary file