ransack 1.7.0 → 1.8.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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +40 -22
  3. data/CHANGELOG.md +176 -27
  4. data/CONTRIBUTING.md +30 -19
  5. data/Gemfile +8 -3
  6. data/README.md +131 -58
  7. data/Rakefile +5 -2
  8. data/lib/ransack.rb +10 -5
  9. data/lib/ransack/adapters.rb +43 -23
  10. data/lib/ransack/adapters/active_record.rb +2 -2
  11. data/lib/ransack/adapters/active_record/3.0/compat.rb +5 -5
  12. data/lib/ransack/adapters/active_record/3.0/context.rb +5 -3
  13. data/lib/ransack/adapters/active_record/3.1/context.rb +1 -4
  14. data/lib/ransack/adapters/active_record/base.rb +12 -1
  15. data/lib/ransack/adapters/active_record/context.rb +148 -55
  16. data/lib/ransack/adapters/active_record/ransack/constants.rb +53 -53
  17. data/lib/ransack/adapters/active_record/ransack/context.rb +3 -1
  18. data/lib/ransack/adapters/active_record/ransack/nodes/condition.rb +20 -28
  19. data/lib/ransack/adapters/mongoid/base.rb +21 -6
  20. data/lib/ransack/adapters/mongoid/context.rb +9 -5
  21. data/lib/ransack/configuration.rb +24 -3
  22. data/lib/ransack/constants.rb +11 -22
  23. data/lib/ransack/context.rb +20 -13
  24. data/lib/ransack/helpers/form_builder.rb +5 -6
  25. data/lib/ransack/helpers/form_helper.rb +50 -69
  26. data/lib/ransack/locale/da.yml +70 -0
  27. data/lib/ransack/locale/id.yml +70 -0
  28. data/lib/ransack/locale/ja.yml +70 -0
  29. data/lib/ransack/locale/pt-BR.yml +70 -0
  30. data/lib/ransack/locale/{zh.yml → zh-CN.yml} +1 -1
  31. data/lib/ransack/locale/zh-TW.yml +70 -0
  32. data/lib/ransack/nodes.rb +1 -1
  33. data/lib/ransack/nodes/attribute.rb +4 -1
  34. data/lib/ransack/nodes/bindable.rb +18 -6
  35. data/lib/ransack/nodes/condition.rb +58 -28
  36. data/lib/ransack/nodes/grouping.rb +15 -4
  37. data/lib/ransack/nodes/sort.rb +9 -5
  38. data/lib/ransack/predicate.rb +6 -2
  39. data/lib/ransack/search.rb +6 -5
  40. data/lib/ransack/translate.rb +2 -2
  41. data/lib/ransack/version.rb +1 -1
  42. data/ransack.gemspec +4 -4
  43. data/spec/mongoid/adapters/mongoid/base_spec.rb +20 -1
  44. data/spec/mongoid/nodes/condition_spec.rb +15 -0
  45. data/spec/mongoid/support/mongoid.yml +5 -0
  46. data/spec/mongoid/support/schema.rb +4 -0
  47. data/spec/mongoid_spec_helper.rb +13 -9
  48. data/spec/ransack/adapters/active_record/base_spec.rb +249 -71
  49. data/spec/ransack/adapters/active_record/context_spec.rb +16 -18
  50. data/spec/ransack/helpers/form_builder_spec.rb +5 -2
  51. data/spec/ransack/helpers/form_helper_spec.rb +84 -14
  52. data/spec/ransack/nodes/condition_spec.rb +24 -0
  53. data/spec/ransack/nodes/grouping_spec.rb +56 -0
  54. data/spec/ransack/predicate_spec.rb +5 -5
  55. data/spec/ransack/search_spec.rb +79 -70
  56. data/spec/support/schema.rb +43 -29
  57. metadata +17 -12
@@ -0,0 +1,70 @@
1
+ da:
2
+ ransack:
3
+ search: "søg"
4
+ predicate: "predicate"
5
+ and: "og"
6
+ or: "eller"
7
+ any: "anhver"
8
+ all: "alle"
9
+ combinator: "kombinering"
10
+ attribute: "attribut"
11
+ value: "værdi"
12
+ condition: "betingelse"
13
+ sort: "sorter"
14
+ asc: "opstigende"
15
+ desc: "faldende"
16
+ predicates:
17
+ eq: "lig med"
18
+ eq_any: "lig med enhver"
19
+ eq_all: "lig med alle"
20
+ not_eq: "ikke lig med"
21
+ not_eq_any: "ikke lig med nogen"
22
+ not_eq_all: "ikke lig med alle"
23
+ matches: "matcher"
24
+ matches_any: "matcher enhver"
25
+ matches_all: "matcher alle"
26
+ does_not_match: "matcher ikke"
27
+ does_not_match_any: "matcher ikke nogen"
28
+ does_not_match_all: "matcher ikke alle"
29
+ lt: "mindre end"
30
+ lt_any: "mindre end nogen"
31
+ lt_all: "mindre end alle"
32
+ lteq: "mindre end eller lig med"
33
+ lteq_any: "mindre end eller lig med nogen"
34
+ lteq_all: "mindre end eller lig med alle"
35
+ gt: "større end"
36
+ gt_any: "større end nogen"
37
+ gt_all: "større end alle"
38
+ gteq: "større end eller lig med"
39
+ gteq_any: "større end eller lig med nogen"
40
+ gteq_all: "større end eller lig med alle"
41
+ in: "i"
42
+ in_any: "i nogen"
43
+ in_all: "i alle"
44
+ not_in: "ikke i"
45
+ not_in_any: "ikke i nogen"
46
+ not_in_all: "ikke i alle"
47
+ cont: "indeholder"
48
+ cont_any: "indeholder nogen"
49
+ cont_all: "indeholder alle"
50
+ not_cont: "indeholder ikke"
51
+ not_cont_any: "indeholder ikke nogen"
52
+ not_cont_all: "indeholder ikke alle"
53
+ start: "starter med"
54
+ start_any: "starter med nogen"
55
+ start_all: "starter med alle"
56
+ not_start: "starter ikke med"
57
+ not_start_any: "starter ikke med nogen"
58
+ not_start_all: "starter ikke med alle"
59
+ end: "slutter med"
60
+ end_any: "slutter med nogen"
61
+ end_all: "slutter med alle"
62
+ not_end: "slutter ikke med"
63
+ not_end_any: "slutter ikke med nogen"
64
+ not_end_all: "slutter ikke med alle"
65
+ 'true': "er sand"
66
+ 'false': "er falsk"
67
+ present: "er til stede"
68
+ blank: "er blank"
69
+ 'null': "er nul"
70
+ not_null: "er ikke nul"
@@ -0,0 +1,70 @@
1
+ id:
2
+ ransack:
3
+ search: "cari"
4
+ predicate: "predikat"
5
+ and: "dan"
6
+ or: "atau"
7
+ any: "apapun"
8
+ all: "semua"
9
+ combinator: "kombinasi"
10
+ attribute: "atribut"
11
+ value: "data"
12
+ condition: "kondisi"
13
+ sort: "urutan"
14
+ asc: "ascending"
15
+ desc: "descending"
16
+ predicates:
17
+ eq: "sama dengan"
18
+ eq_any: "sama beberapa dengan"
19
+ eq_all: "sama seluruhnya dengan"
20
+ not_eq: "tidak sama dengan"
21
+ not_eq_any: "tidak sama beberapa dengan"
22
+ not_eq_all: "tidak semua seluruhnya dengan"
23
+ matches: "mirip"
24
+ matches_any: "mirip beberapa dengan"
25
+ matches_all: "mirip semua dengan"
26
+ does_not_match: "tidak mirip dengan"
27
+ does_not_match_any: "tidak mirip beberapa dengan"
28
+ does_not_match_all: "tidak mirip semua dengan"
29
+ lt: "kurang dari"
30
+ lt_any: "kurang beberapa dengan"
31
+ lt_all: "kurang seluruhnya dengan"
32
+ lteq: "kurang lebih"
33
+ lteq_any: "kurang lebih beberapa dengan"
34
+ lteq_all: "kurang lebih semua dengan"
35
+ gt: "lebih besar daripada"
36
+ gt_any: "lebih besar beberapa dengan"
37
+ gt_all: "lebih besar semua dengan"
38
+ gteq: "lebih besar atau sama dengan"
39
+ gteq_any: "beberapa lebih besar atau sama dengan"
40
+ gteq_all: "semua lebih besar atau sama dengan"
41
+ in: "di"
42
+ in_any: "di beberapa"
43
+ in_all: "di semua"
44
+ not_in: "tidak di"
45
+ not_in_any: "tidak di beberapa"
46
+ not_in_all: "tidak semua di"
47
+ cont: "mengandung"
48
+ cont_any: "mengandung beberapa"
49
+ cont_all: "mengandung semua"
50
+ not_cont: "tidak mengandung"
51
+ not_cont_any: "tidak mengandung beberapa"
52
+ not_cont_all: "tidak mengandung semua"
53
+ start: "diawali dengan"
54
+ start_any: "diawali beberapa dengan"
55
+ start_all: "diawali semua dengan"
56
+ not_start: "tidak diawali dengan"
57
+ not_start_any: "tidak diawali beberapa dengan"
58
+ not_start_all: "tidak diawali semua dengan"
59
+ end: "diakhiri dengan"
60
+ end_any: "diakhiri beberapa dengan"
61
+ end_all: "diakhiri semua dengan"
62
+ not_end: "tidak diakhiri dengan"
63
+ not_end_any: "tidak diakhiri dengan beberapa"
64
+ not_end_all: "tidak diakhiri dengan semua"
65
+ 'true': "bernilai benar"
66
+ 'false': "bernilai salah"
67
+ present: "ada"
68
+ blank: "kosong"
69
+ 'null': "null"
70
+ not_null: "tidak null"
@@ -0,0 +1,70 @@
1
+ ja:
2
+ ransack:
3
+ search: "検索"
4
+ predicate: "は以下である"
5
+ and: "と"
6
+ or: "あるいは"
7
+ any: "いずれか"
8
+ all: "全て"
9
+ combinator: "組み合わせ"
10
+ attribute: "属性"
11
+ value: "値"
12
+ condition: "状態"
13
+ sort: "分類"
14
+ asc: "昇順"
15
+ desc: "降順"
16
+ predicates:
17
+ eq: "は以下と等しい"
18
+ eq_any: "は以下のいずれかに等しい"
19
+ eq_all: "は以下の全てに等しい"
20
+ not_eq: "は以下と等しくない"
21
+ not_eq_any: "は以下のいずれかに等しくない"
22
+ not_eq_all: "は以下の全てと等しくない"
23
+ matches: "は以下と合致している"
24
+ matches_any: "は以下のいずれかと合致している"
25
+ matches_all: "は以下の全てと合致している"
26
+ does_not_match: "は以下と合致していない"
27
+ does_not_match_any: "は以下のいずれかに合致していない"
28
+ does_not_match_all: "は以下の全てに合致していない"
29
+ lt: "は以下よりも小さい"
30
+ lt_any: "は以下のいずれかより小さい"
31
+ lt_all: "は以下の全てよりも小さい"
32
+ lteq: "は以下より小さいか等しい"
33
+ lteq_any: "は以下のいずれかより小さいか等しい"
34
+ lteq_all: "は以下の全てより小さいか等しい"
35
+ gt: "は以下より大きい"
36
+ gt_any: "は以下のいずれかより大きい"
37
+ gt_all: "は以下の全てより大きい"
38
+ gteq: "は以下より大きいか等しい"
39
+ gteq_any: "は以下のいずれかより大きいか等しい"
40
+ gteq_all: "は以下の全てより大きいか等しい"
41
+ in: "は以下の範囲内である"
42
+ in_any: "は以下のいずれかの範囲内である"
43
+ in_all: "は以下の全ての範囲内である"
44
+ not_in: "は以下の範囲内でない"
45
+ not_in_any: "は以下のいずれかの範囲内でない"
46
+ not_in_all: "は以下の全ての範囲内"
47
+ cont: "は以下を含む"
48
+ cont_any: "はいずれかを含む"
49
+ cont_all: "は以下の全てを含む"
50
+ not_cont: "は含まない"
51
+ not_cont_any: "は以下のいずれかを含まない"
52
+ not_cont_all: "は以下の全てを含まない"
53
+ start: "は以下で始まる"
54
+ start_any: "は以下のどれかで始まる"
55
+ start_all: "は以下の全てで始まる"
56
+ not_start: "は以下で始まらない"
57
+ not_start_any: "は以下のいずれかで始まらない"
58
+ not_start_all: "は以下の全てで始まらない"
59
+ end: "は以下で終わる"
60
+ end_any: "は以下のいずれかで終わる"
61
+ end_all: "は以下の全てで終わる"
62
+ not_end: "は以下のどれでも終わらない"
63
+ not_end_any: "は以下のいずれかで終わらない"
64
+ not_end_all: "は以下の全てで終わらない"
65
+ 'true': "真"
66
+ 'false': "偽"
67
+ present: "は存在する"
68
+ blank: "は空である"
69
+ 'null': "無効"
70
+ not_null: "は無効ではない"
@@ -0,0 +1,70 @@
1
+ pt-BR:
2
+ ransack:
3
+ search: "pesquisar"
4
+ predicate: "predicado"
5
+ and: "e"
6
+ or: "ou"
7
+ any: "algum"
8
+ all: "todos"
9
+ combinator: "combinador"
10
+ attribute: "atributo"
11
+ value: "valor"
12
+ condition: "condição"
13
+ sort: "classificar"
14
+ asc: "ascendente"
15
+ desc: "descendente"
16
+ predicates:
17
+ eq: "igual"
18
+ eq_any: "igual a algum"
19
+ eq_all: "igual a todos"
20
+ not_eq: "não é igual a"
21
+ not_eq_any: "não é igual a algum"
22
+ not_eq_all: "não é igual a todos"
23
+ matches: "corresponde"
24
+ matches_any: "corresponde a algum"
25
+ matches_all: "corresponde a todos"
26
+ does_not_match: "não corresponde"
27
+ does_not_match_any: "não corresponde a algum"
28
+ does_not_match_all: "não corresponde a todos"
29
+ lt: "menor que"
30
+ lt_any: "menor que algum"
31
+ lt_all: "menor que todos"
32
+ lteq: "menor ou igual a"
33
+ lteq_any: "menor ou igual a algum"
34
+ lteq_all: "menor ou igual a todos"
35
+ gt: "maior que"
36
+ gt_any: "maior que algum"
37
+ gt_all: "maior que todos"
38
+ gteq: "maior que ou igual a"
39
+ gteq_any: "maior que ou igual a algum"
40
+ gteq_all: "maior que ou igual a todos"
41
+ in: "em"
42
+ in_any: "em algum"
43
+ in_all: "em todos"
44
+ not_in: "não em"
45
+ not_in_any: "não em algum"
46
+ not_in_all: "não em todos"
47
+ cont: "contém"
48
+ cont_any: "contém algum"
49
+ cont_all: "contém todos"
50
+ not_cont: "não contém"
51
+ not_cont_any: "não contém algum"
52
+ not_cont_all: "não contém todos"
53
+ start: "começa com"
54
+ start_any: "começa com algum"
55
+ start_all: "começa com todos"
56
+ not_start: "não começa com"
57
+ not_start_any: "não começa com algum"
58
+ not_start_all: "não começa com algum"
59
+ end: "termina com"
60
+ end_any: "termina com algum"
61
+ end_all: "termina com todos"
62
+ not_end: "não termina com"
63
+ not_end_any: "não termina com algum"
64
+ not_end_all: "não termina com todos"
65
+ 'true': "é verdadeiro"
66
+ 'false': "é falso"
67
+ present: "está presente"
68
+ blank: "está em branco"
69
+ 'null': "é nulo"
70
+ not_null: "não é nulo"
@@ -1,4 +1,4 @@
1
- zh:
1
+ zh-CN:
2
2
  ransack:
3
3
  search: "搜索"
4
4
  predicate: "基于(predicate)"
@@ -0,0 +1,70 @@
1
+ zh-TW:
2
+ ransack:
3
+ search: "搜尋"
4
+ predicate: "基於"
5
+ and: "而且"
6
+ or: "或者"
7
+ any: "任何"
8
+ all: "所有"
9
+ combinator: "條件組合"
10
+ attribute: "屬性"
11
+ value: "數值"
12
+ condition: "條件"
13
+ sort: "排序"
14
+ asc: "升冪排序"
15
+ desc: "降冪排序"
16
+ predicates:
17
+ eq: "等於"
18
+ eq_any: "等於任何一個值"
19
+ eq_all: "等於所有值"
20
+ not_eq: "不等於"
21
+ not_eq_any: "不等於任何一個值"
22
+ not_eq_all: "不等於所有值"
23
+ matches: "符合"
24
+ matches_any: "符合任何一個條件"
25
+ matches_all: "符合所有條件"
26
+ does_not_match: "不符合"
27
+ does_not_match_any: "不符合任何一個條件"
28
+ does_not_match_all: "不符合所有條件"
29
+ lt: "小於"
30
+ lt_any: "小於任何一個值"
31
+ lt_all: "小於所有值"
32
+ lteq: "小於或等於"
33
+ lteq_any: "小於或等於任何一個值"
34
+ lteq_all: "小於或等於所有值"
35
+ gt: "大於"
36
+ gt_any: "大於任何一個值"
37
+ gt_all: "大於所有值"
38
+ gteq: "大於或等於"
39
+ gteq_any: "大於或等於任何一個值"
40
+ gteq_all: "大於或等於所有值"
41
+ in: "被包含於"
42
+ in_any: "被包含於任何一個值"
43
+ in_all: "被包含於所有值"
44
+ not_in: "不被包含於"
45
+ not_in_any: "不被包含於任何一個值"
46
+ not_in_all: "不被包含於所有值"
47
+ cont: "包含"
48
+ cont_any: "包含任何一個值"
49
+ cont_all: "包含所有值"
50
+ not_cont: "不包含"
51
+ not_cont_any: "不包含任何一個值"
52
+ not_cont_all: "不包含所有值"
53
+ start: "以某個值開始"
54
+ start_any: "以任何一個值開始"
55
+ start_all: "以所有值開始"
56
+ not_start: "不以某個值開始"
57
+ not_start_any: "不以任何一值開始"
58
+ not_start_all: "不以所有值開始"
59
+ end: "以某個值結尾"
60
+ end_any: "以任何一個值結尾"
61
+ end_all: "以所有值結尾"
62
+ not_end: "不以某個值結尾"
63
+ not_end_any: "不以任何一個值結尾"
64
+ not_end_all: "不以所有值結尾"
65
+ 'true': "為真"
66
+ 'false': "為假"
67
+ present: "有值"
68
+ blank: "為空"
69
+ 'null': "為 null"
70
+ not_null: "不為 null"
@@ -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'
@@ -16,7 +16,6 @@ module Ransack
16
16
 
17
17
  def name=(name)
18
18
  @name = name
19
- context.bind(self, name) unless name.blank?
20
19
  end
21
20
 
22
21
  def valid?
@@ -25,6 +24,10 @@ module Ransack
25
24
  .include?(attr_name.split('.').last)
26
25
  end
27
26
 
27
+ def associated_collection?
28
+ parent.respond_to?(:reflection) && parent.reflection.collection?
29
+ end
30
+
28
31
  def type
29
32
  if ransacker
30
33
  return ransacker.type
@@ -27,14 +27,26 @@ module Ransack
27
27
 
28
28
  private
29
29
 
30
- def get_arel_attribute
31
- if ransacker
32
- ransacker.attr_from(self)
33
- else
34
- context.table_for(parent)[attr_name]
35
- end
30
+ def get_arel_attribute
31
+ if ransacker
32
+ ransacker.attr_from(self)
33
+ else
34
+ get_attribute
36
35
  end
36
+ end
37
37
 
38
+ def get_attribute
39
+ if is_alias_attribute?
40
+ context.table_for(parent)[parent.base_klass.attribute_aliases[attr_name]]
41
+ else
42
+ context.table_for(parent)[attr_name]
43
+ end
44
+ end
45
+
46
+ def is_alias_attribute?
47
+ Ransack::SUPPORTS_ATTRIBUTE_ALIAS &&
48
+ parent.base_klass.attribute_aliases.key?(attr_name)
49
+ end
38
50
  end
39
51
  end
40
52
  end
@@ -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,13 @@ 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
+ def build_attribute(name = nil, ransacker_args = [])
131
+ Attribute.new(@context, name, ransacker_args).tap do |attribute|
132
+ @context.bind(attribute, attribute.name)
133
+ self.attributes << attribute if attribute.valid?
134
+ if predicate && !negative?
135
+ @context.lock_association(attribute.parent)
136
+ end
120
137
  end
121
138
  end
122
139
 
@@ -168,6 +185,10 @@ module Ransack
168
185
 
169
186
  def predicate_name=(name)
170
187
  self.predicate = Predicate.named(name)
188
+ unless negative?
189
+ attributes.each { |a| context.lock_association(a.parent) }
190
+ end
191
+ @predicate
171
192
  end
172
193
  alias :p= :predicate_name=
173
194
 
@@ -196,15 +217,20 @@ module Ransack
196
217
  val = predicate.format(val)
197
218
  val
198
219
  end
199
- predicate.wants_array ? formatted : formatted.first
220
+ if predicate.wants_array
221
+ formatted
222
+ else
223
+ formatted.first
224
+ end
200
225
  end
201
226
 
202
227
  def arel_predicate_for_attribute(attr)
203
228
  if predicate.arel_predicate === Proc
204
229
  values = casted_values_for_attribute(attr)
205
- predicate.arel_predicate.call(
206
- predicate.wants_array ? values : values.first
207
- )
230
+ unless predicate.wants_array
231
+ values = values.first
232
+ end
233
+ predicate.arel_predicate.call(values)
208
234
  else
209
235
  predicate.arel_predicate
210
236
  end
@@ -224,10 +250,14 @@ module Ransack
224
250
  ]
225
251
  .reject { |e| e[1].blank? }
226
252
  .map { |v| "#{v[0]}: #{v[1]}" }
227
- .join(Constants::COMMA_SPACE)
253
+ .join(', '.freeze)
228
254
  "Condition <#{data}>"
229
255
  end
230
256
 
257
+ def negative?
258
+ predicate.negative?
259
+ end
260
+
231
261
  private
232
262
 
233
263
  def valid_combinator?