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
@@ -3,48 +3,51 @@ module Ransack
3
3
  class Condition
4
4
 
5
5
  def arel_predicate
6
- arel_predicate_for(attributes_array)
6
+ attributes.map { |attribute|
7
+ association = attribute.parent
8
+ if negative? && attribute.associated_collection?
9
+ query = context.build_correlated_subquery(association)
10
+ context.remove_association(association)
11
+ if self.predicate_name == 'not_null' && self.value
12
+ query.where(format_predicate(attribute))
13
+ Arel::Nodes::In.new(context.primary_key, Arel.sql(query.to_sql))
14
+ else
15
+ query.where(format_predicate(attribute).not)
16
+ Arel::Nodes::NotIn.new(context.primary_key, Arel.sql(query.to_sql))
17
+ end
18
+ else
19
+ format_predicate(attribute)
20
+ end
21
+ }.reduce(combinator_method)
7
22
  end
8
23
 
9
24
  private
10
25
 
11
- def attributes_array
12
- attributes.map do |a|
13
- a.attr.send(
14
- arel_predicate_for_attribute(a), formatted_values_for_attribute(a)
15
- )
16
- end
26
+ def combinator_method
27
+ combinator === Constants::OR ? :or : :and
17
28
  end
18
29
 
19
- def arel_predicate_for(predicates)
20
- if predicates.size > 1
21
- combinator_for(predicates)
22
- else
23
- format_predicate(predicates.first)
24
- end
25
- end
30
+ def format_predicate(attribute)
31
+ arel_pred = arel_predicate_for_attribute(attribute)
32
+ arel_values = formatted_values_for_attribute(attribute)
33
+ predicate = attribute.attr.public_send(arel_pred, arel_values)
26
34
 
27
- def combinator_for(predicates)
28
- if combinator === Constants::AND
29
- Arel::Nodes::Grouping.new(Arel::Nodes::And.new(predicates))
30
- elsif combinator === Constants::OR
31
- predicates.inject(&:or)
32
- end
33
- end
34
-
35
- def format_predicate(predicate)
36
- predicate.tap do
37
- if casted_array_with_in_predicate?(predicate)
38
- predicate.right[0] = format_values_for(predicate.right[0])
35
+ if in_predicate?(predicate)
36
+ predicate.right = predicate.right.map do |pr|
37
+ casted_array?(pr) ? format_values_for(pr) : pr
39
38
  end
40
39
  end
40
+
41
+ predicate
41
42
  end
42
43
 
43
- def casted_array_with_in_predicate?(predicate)
44
+ def in_predicate?(predicate)
44
45
  return unless defined?(Arel::Nodes::Casted)
45
- predicate.class == Arel::Nodes::In &&
46
- predicate.right[0].respond_to?(:val) &&
47
- predicate.right[0].val.is_a?(Array)
46
+ predicate.class == Arel::Nodes::In
47
+ end
48
+
49
+ def casted_array?(predicate)
50
+ predicate.respond_to?(:val) && predicate.val.is_a?(Array)
48
51
  end
49
52
 
50
53
  def format_values_for(predicate)
@@ -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
@@ -20,5 +20,28 @@ module Ransack
20
20
  end
21
21
  end
22
22
 
23
+ def visit_Ransack_Nodes_Sort(object)
24
+ if object.valid?
25
+ if object.attr.is_a?(Arel::Attributes::Attribute)
26
+ object.attr.send(object.dir)
27
+ else
28
+ ordered(object)
29
+ end
30
+ else
31
+ scope_name = :"sort_by_#{object.name}_#{object.dir}"
32
+ scope_name if object.context.object.respond_to?(scope_name)
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def ordered(object)
39
+ case object.dir
40
+ when 'asc'.freeze
41
+ Arel::Nodes::Ascending.new(object.attr)
42
+ when 'desc'.freeze
43
+ Arel::Nodes::Descending.new(object.attr)
44
+ end
45
+ end
23
46
  end
24
47
  end
@@ -1,13 +1,14 @@
1
1
  require 'ransack/adapters/active_record/base'
2
- ActiveRecord::Base.extend Ransack::Adapters::ActiveRecord::Base
3
2
 
4
- case ActiveRecord::VERSION::STRING
5
- when /^3\.0\./
6
- require 'ransack/adapters/active_record/3.0/context'
7
- when /^3\.1\./
8
- require 'ransack/adapters/active_record/3.1/context'
9
- when /^3\.2\./
10
- require 'ransack/adapters/active_record/3.2/context'
11
- else
12
- require 'ransack/adapters/active_record/context'
3
+ ActiveSupport.on_load(:active_record) do
4
+ extend Ransack::Adapters::ActiveRecord::Base
5
+
6
+ Ransack::SUPPORTS_ATTRIBUTE_ALIAS =
7
+ begin
8
+ ActiveRecord::Base.respond_to?(:attribute_aliases)
9
+ rescue NameError
10
+ false
11
+ end
13
12
  end
13
+
14
+ require 'ransack/adapters/active_record/context'
@@ -1,42 +1,64 @@
1
1
  module Ransack
2
2
  module Adapters
3
3
 
4
- def self.current_adapters
5
- @current_adapters ||= {
6
- :active_record => defined?(::ActiveRecord::Base),
7
- :mongoid => defined?(::Mongoid) && !defined?(::ActiveRecord::Base)
8
- }
4
+ def self.object_mapper
5
+ @object_mapper ||= instantiate_object_mapper
9
6
  end
10
- def self.require_constants
11
- require 'ransack/adapters/mongoid/ransack/constants' if current_adapters[:mongoid]
12
- require 'ransack/adapters/active_record/ransack/constants' if current_adapters[:active_record]
7
+
8
+ def self.instantiate_object_mapper
9
+ if defined?(::ActiveRecord::Base)
10
+ ActiveRecordAdapter.new
11
+ elsif defined?(::Mongoid)
12
+ MongoidAdapter.new
13
+ else
14
+ raise "Unsupported adapter"
15
+ end
13
16
  end
14
17
 
15
- def self.require_adapter
16
- if current_adapters[:active_record]
18
+ class ActiveRecordAdapter
19
+ def require_constants
20
+ require 'ransack/adapters/active_record/ransack/constants'
21
+ end
22
+
23
+ def require_adapter
17
24
  require 'ransack/adapters/active_record/ransack/translate'
18
25
  require 'ransack/adapters/active_record'
19
26
  end
20
27
 
21
- if current_adapters[:mongoid]
28
+ def require_context
29
+ require 'ransack/adapters/active_record/ransack/visitor'
30
+ end
31
+
32
+ def require_nodes
33
+ require 'ransack/adapters/active_record/ransack/nodes/condition'
34
+ end
35
+
36
+ def require_search
37
+ require 'ransack/adapters/active_record/ransack/context'
38
+ end
39
+ end
40
+
41
+ class MongoidAdapter
42
+ def require_constants
43
+ require 'ransack/adapters/mongoid/ransack/constants'
44
+ end
45
+
46
+ def require_adapter
22
47
  require 'ransack/adapters/mongoid/ransack/translate'
23
48
  require 'ransack/adapters/mongoid'
24
49
  end
25
- end
26
50
 
27
- def self.require_context
28
- require 'ransack/adapters/active_record/ransack/visitor' if current_adapters[:active_record]
29
- require 'ransack/adapters/mongoid/ransack/visitor' if current_adapters[:mongoid]
30
- end
51
+ def require_context
52
+ require 'ransack/adapters/mongoid/ransack/visitor'
53
+ end
31
54
 
32
- def self.require_nodes
33
- require 'ransack/adapters/active_record/ransack/nodes/condition' if current_adapters[:active_record]
34
- require 'ransack/adapters/mongoid/ransack/nodes/condition' if current_adapters[:mongoid]
35
- end
55
+ def require_nodes
56
+ require 'ransack/adapters/mongoid/ransack/nodes/condition'
57
+ end
36
58
 
37
- def self.require_search
38
- require 'ransack/adapters/active_record/ransack/context' if current_adapters[:active_record]
39
- require 'ransack/adapters/mongoid/ransack/context' if current_adapters[:mongoid]
59
+ def require_search
60
+ require 'ransack/adapters/mongoid/ransack/context'
61
+ end
40
62
  end
41
63
  end
42
64
  end
@@ -5,10 +5,35 @@ module Ransack
5
5
  module Configuration
6
6
 
7
7
  mattr_accessor :predicates, :options
8
- self.predicates = {}
8
+
9
+ class PredicateCollection
10
+ attr_reader :sorted_names_with_underscores
11
+
12
+ def initialize
13
+ @collection = {}
14
+ @sorted_names_with_underscores = []
15
+ end
16
+
17
+ delegate :[], :keys, :has_key?, to: :@collection
18
+
19
+ def []=(key, value)
20
+ @sorted_names_with_underscores << [key, '_' + key]
21
+ @sorted_names_with_underscores.sort! { |(a, _), (b, _)| b.length <=> a.length }
22
+
23
+ @collection[key] = value
24
+ end
25
+ end
26
+
27
+ self.predicates = PredicateCollection.new
28
+
9
29
  self.options = {
10
30
  :search_key => :q,
11
- :ignore_unknown_conditions => true
31
+ :ignore_unknown_conditions => true,
32
+ :hide_sort_order_indicators => false,
33
+ :up_arrow => '&#9660;'.freeze,
34
+ :down_arrow => '&#9650;'.freeze,
35
+ :default_arrow => nil,
36
+ :sanitize_scope_args => true
12
37
  }
13
38
 
14
39
  def configure
@@ -61,12 +86,74 @@ module Ransack
61
86
  self.options[:search_key] = name
62
87
  end
63
88
 
64
- # Raise an error if an unknown predicate, condition or attribute is passed
65
- # into a search.
89
+ # By default Ransack ignores errors if an unknown predicate, condition or
90
+ # attribute is passed into a search. The default may be overridden in an
91
+ # initializer file like `config/initializers/ransack.rb` as follows:
92
+ #
93
+ # Ransack.configure do |config|
94
+ # # Raise if an unknown predicate, condition or attribute is passed
95
+ # config.ignore_unknown_conditions = false
96
+ # end
97
+ #
66
98
  def ignore_unknown_conditions=(boolean)
67
99
  self.options[:ignore_unknown_conditions] = boolean
68
100
  end
69
101
 
102
+ # By default, Ransack displays sort order indicator arrows with HTML codes:
103
+ #
104
+ # up_arrow: '&#9660;'
105
+ # down_arrow: '&#9650;'
106
+ #
107
+ # There is also a default arrow which is displayed if a column is not sorted.
108
+ # By default this is nil so nothing will be displayed.
109
+ #
110
+ # Any of the defaults may be globally overridden in an initializer file
111
+ # like `config/initializers/ransack.rb` as follows:
112
+ #
113
+ # Ransack.configure do |config|
114
+ # # Globally set the up arrow to an icon, and the down and default arrows to unicode.
115
+ # config.custom_arrows = {
116
+ # up_arrow: '<i class="fa fa-long-arrow-up"></i>',
117
+ # down_arrow: 'U+02193',
118
+ # default_arrow: 'U+11047'
119
+ # }
120
+ # end
121
+ #
122
+ def custom_arrows=(opts = {})
123
+ self.options[:up_arrow] = opts[:up_arrow].freeze if opts[:up_arrow]
124
+ self.options[:down_arrow] = opts[:down_arrow].freeze if opts[:down_arrow]
125
+ self.options[:default_arrow] = opts[:default_arrow].freeze if opts[:default_arrow]
126
+ end
127
+
128
+ # Ransack sanitizes many values in your custom scopes into booleans.
129
+ # [1, '1', 't', 'T', 'true', 'TRUE'] all evaluate to true.
130
+ # [0, '0', 'f', 'F', 'false', 'FALSE'] all evaluate to false.
131
+ #
132
+ # This default may be globally overridden in an initializer file like
133
+ # `config/initializers/ransack.rb` as follows:
134
+ #
135
+ # Ransack.configure do |config|
136
+ # # Accept my custom scope values as what they are.
137
+ # config.sanitize_custom_scope_booleans = false
138
+ # end
139
+ #
140
+ def sanitize_custom_scope_booleans=(boolean)
141
+ self.options[:sanitize_scope_args] = boolean
142
+ end
143
+
144
+ # By default, Ransack displays sort order indicator arrows in sort links.
145
+ # The default may be globally overridden in an initializer file like
146
+ # `config/initializers/ransack.rb` as follows:
147
+ #
148
+ # Ransack.configure do |config|
149
+ # # Hide sort link order indicators globally across the application
150
+ # config.hide_sort_order_indicators = true
151
+ # end
152
+ #
153
+ def hide_sort_order_indicators=(boolean)
154
+ self.options[:hide_sort_order_indicators] = boolean
155
+ end
156
+
70
157
  def arel_predicate_with_suffix(arel_predicate, suffix)
71
158
  if arel_predicate === Proc
72
159
  proc { |v| "#{arel_predicate.call(v)}#{suffix}" }
@@ -1,19 +1,7 @@
1
1
  module Ransack
2
2
  module Constants
3
- ASC = 'asc'.freeze
4
- DESC = 'desc'.freeze
5
- ASC_DESC = [ASC, DESC].freeze
6
-
7
- ASC_ARROW = '&#9650;'.freeze
8
- DESC_ARROW = '&#9660;'.freeze
9
-
10
3
  OR = 'or'.freeze
11
4
  AND = 'and'.freeze
12
- SPACED_AND = ' AND '.freeze
13
-
14
- SORT = 'sort'.freeze
15
- SORT_LINK = 'sort_link'.freeze
16
- SORT_DIRECTION = 'sort_direction'.freeze
17
5
 
18
6
  CAP_SEARCH = 'Search'.freeze
19
7
  SEARCH = 'search'.freeze
@@ -23,17 +11,12 @@ module Ransack
23
11
  ATTRIBUTES = 'attributes'.freeze
24
12
  COMBINATOR = 'combinator'.freeze
25
13
 
26
- SPACE = ' '.freeze
27
- COMMA_SPACE = ', '.freeze
28
- COLON_SPACE = ': '.freeze
29
14
  TWO_COLONS = '::'.freeze
30
15
  UNDERSCORE = '_'.freeze
31
16
  LEFT_PARENTHESIS = '('.freeze
32
17
  Q = 'q'.freeze
33
18
  I = 'i'.freeze
34
- NON_BREAKING_SPACE = '&nbsp;'.freeze
35
19
  DOT_ASTERIX = '.*'.freeze
36
- EMPTY = ''.freeze
37
20
 
38
21
  STRING_JOIN = 'string_join'.freeze
39
22
  ASSOCIATION_JOIN = 'association_join'.freeze
@@ -44,14 +27,17 @@ module Ransack
44
27
  FALSE_VALUES = [false, 0, '0', 'f', 'F', 'false', 'FALSE'].to_set
45
28
  BOOLEAN_VALUES = (TRUE_VALUES + FALSE_VALUES).freeze
46
29
 
47
- S_SORTS = %w(s sorts).freeze
48
- AND_OR = %w(and or).freeze
49
- IN_NOT_IN = %w(in not_in).freeze
50
- SUFFIXES = %w(_any _all).freeze
51
- AREL_PREDICATES = %w(
52
- eq not_eq matches does_not_match lt lteq gt gteq in not_in
53
- ).freeze
54
- A_S_I = %w(a s i).freeze
30
+ AND_OR = ['and'.freeze, 'or'.freeze].freeze
31
+ IN_NOT_IN = ['in'.freeze, 'not_in'.freeze].freeze
32
+ SUFFIXES = ['_any'.freeze, '_all'.freeze].freeze
33
+ AREL_PREDICATES = [
34
+ 'eq'.freeze, 'not_eq'.freeze,
35
+ 'matches'.freeze, 'does_not_match'.freeze,
36
+ 'lt'.freeze, 'lteq'.freeze,
37
+ 'gt'.freeze, 'gteq'.freeze,
38
+ 'in'.freeze, 'not_in'.freeze
39
+ ].freeze
40
+ A_S_I = ['a'.freeze, 's'.freeze, 'i'.freeze].freeze
55
41
 
56
42
  EQ = 'eq'.freeze
57
43
  NOT_EQ = 'not_eq'.freeze
@@ -59,7 +45,9 @@ module Ransack
59
45
  NOT_EQ_ALL = 'not_eq_all'.freeze
60
46
  CONT = 'cont'.freeze
61
47
 
62
- RAILS_4_1 = '4.1'.freeze
48
+ RAILS_5_1 = '5.1'.freeze
49
+ RAILS_5_2 = '5.2'.freeze
50
+ RAILS_5_2_0 = '5.2.0'.freeze
63
51
 
64
52
  RANSACK_SLASH_SEARCHES = 'ransack/searches'.freeze
65
53
  RANSACK_SLASH_SEARCHES_SLASH_SEARCH = 'ransack/searches/search'.freeze
@@ -1,5 +1,5 @@
1
1
  require 'ransack/visitor'
2
- Ransack::Adapters.require_context
2
+ Ransack::Adapters.object_mapper.require_context
3
3
 
4
4
  module Ransack
5
5
  class Context
@@ -17,9 +17,12 @@ module Ransack
17
17
  end
18
18
 
19
19
  def for(object, options = {})
20
- context = Class === object ?
21
- for_class(object, options) :
22
- for_object(object, options)
20
+ context =
21
+ if Class === object
22
+ for_class(object, options)
23
+ else
24
+ for_object(object, options)
25
+ end
23
26
  context or raise ArgumentError,
24
27
  "Don't know what context to use for #{object}"
25
28
  end
@@ -37,7 +40,7 @@ module Ransack
37
40
  # Convert a string representing a chain of associations and an attribute
38
41
  # into the attribute itself
39
42
  def contextualize(str)
40
- parent, attr_name = @bind_pairs[str]
43
+ parent, attr_name = bind_pair_for(str)
41
44
  table_for(parent)[attr_name]
42
45
  end
43
46
 
@@ -55,13 +58,14 @@ module Ransack
55
58
  end
56
59
 
57
60
  def bind(object, str)
58
- object.parent, object.attr_name = @bind_pairs[str]
61
+ return nil unless str
62
+ object.parent, object.attr_name = bind_pair_for(str)
59
63
  end
60
64
 
61
65
  def traverse(str, base = @base)
62
- str ||= Constants::EMPTY
66
+ str ||= ''.freeze
63
67
 
64
- if (segments = str.split(/_/)).size > 0
68
+ if (segments = str.split(Constants::UNDERSCORE)).size > 0
65
69
  remainder = []
66
70
  found_assoc = nil
67
71
  while !found_assoc && segments.size > 0 do
@@ -72,9 +76,8 @@ module Ransack
72
76
  )
73
77
  if found_assoc = get_association(assoc, base)
74
78
  base = traverse(
75
- remainder.join(
76
- Constants::UNDERSCORE), klass || found_assoc.klass
77
- )
79
+ remainder.join(Constants::UNDERSCORE), klass || found_assoc.klass
80
+ )
78
81
  end
79
82
 
80
83
  remainder.unshift segments.pop
@@ -88,11 +91,11 @@ module Ransack
88
91
 
89
92
  def association_path(str, base = @base)
90
93
  base = klassify(base)
91
- str ||= Constants::EMPTY
94
+ str ||= ''.freeze
92
95
  path = []
93
- segments = str.split(/_/)
96
+ segments = str.split(Constants::UNDERSCORE)
94
97
  association_parts = []
95
- if (segments = str.split(/_/)).size > 0
98
+ if (segments = str.split(Constants::UNDERSCORE)).size > 0
96
99
  while segments.size > 0 &&
97
100
  !base.columns_hash[segments.join(Constants::UNDERSCORE)] &&
98
101
  association_parts << segments.shift do
@@ -118,6 +121,10 @@ module Ransack
118
121
  end
119
122
  end
120
123
 
124
+ def ransackable_alias(str)
125
+ klass._ransack_aliases.fetch(str, str)
126
+ end
127
+
121
128
  def ransackable_attribute?(str, klass)
122
129
  klass.ransackable_attributes(auth_object).include?(str) ||
123
130
  klass.ransortable_attributes(auth_object).include?(str)
@@ -128,18 +135,22 @@ module Ransack
128
135
  end
129
136
 
130
137
  def ransackable_scope?(str, klass)
131
- klass.ransackable_scopes(auth_object).any? { |s| s.to_s == str }
138
+ klass.ransackable_scopes(auth_object).any? { |s| s.to_sym == str.to_sym }
139
+ end
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 }
132
143
  end
133
144
 
134
- def searchable_attributes(str = Constants::EMPTY)
145
+ def searchable_attributes(str = ''.freeze)
135
146
  traverse(str).ransackable_attributes(auth_object)
136
147
  end
137
148
 
138
- def sortable_attributes(str = Constants::EMPTY)
149
+ def sortable_attributes(str = ''.freeze)
139
150
  traverse(str).ransortable_attributes(auth_object)
140
151
  end
141
152
 
142
- def searchable_associations(str = Constants::EMPTY)
153
+ def searchable_associations(str = ''.freeze)
143
154
  traverse(str).ransackable_associations(auth_object)
144
155
  end
145
156
  end
@@ -6,8 +6,20 @@ module ActionView::Helpers::Tags
6
6
  # https://github.com/rails/rails/commit/c1a118a
7
7
  class Base
8
8
  private
9
- def value(object)
10
- object.send @method_name if object # use send instead of public_send
9
+ if defined? ::ActiveRecord
10
+ if ::ActiveRecord::VERSION::STRING < '5.2'
11
+ def value(object)
12
+ object.send @method_name if object # use send instead of public_send
13
+ end
14
+ else # rails/rails#29791
15
+ def value
16
+ if @allow_method_names_outside_object
17
+ object.send @method_name if object && object.respond_to?(@method_name, true)
18
+ else
19
+ object.send @method_name if object
20
+ end
21
+ end
22
+ end
11
23
  end
12
24
  end
13
25
  end
@@ -15,8 +27,7 @@ end
15
27
  RANSACK_FORM_BUILDER = 'RANSACK_FORM_BUILDER'.freeze
16
28
 
17
29
  require 'simple_form' if
18
- (ENV[RANSACK_FORM_BUILDER] || Ransack::Constants::EMPTY)
19
- .match('SimpleForm'.freeze)
30
+ (ENV[RANSACK_FORM_BUILDER] || ''.freeze).match('SimpleForm'.freeze)
20
31
 
21
32
  module Ransack
22
33
  module Helpers
@@ -47,7 +58,7 @@ module Ransack
47
58
  raise ArgumentError, formbuilder_error_message(
48
59
  "#{action}_select") unless object.respond_to?(:context)
49
60
  options[:include_blank] = true unless options.has_key?(:include_blank)
50
- bases = [Constants::EMPTY] + association_array(options[:associations])
61
+ bases = [''.freeze].freeze + association_array(options[:associations])
51
62
  if bases.size > 1
52
63
  collection = attribute_collection_for_bases(action, bases)
53
64
  object.name ||= default if can_use_default?(
@@ -66,13 +77,13 @@ module Ransack
66
77
  def sort_direction_select(options = {}, html_options = {})
67
78
  unless object.respond_to?(:context)
68
79
  raise ArgumentError,
69
- formbuilder_error_message(Constants::SORT_DIRECTION)
80
+ formbuilder_error_message('sort_direction'.freeze)
70
81
  end
71
82
  template_collection_select(:dir, sort_array, options, html_options)
72
83
  end
73
84
 
74
85
  def sort_select(options = {}, html_options = {})
75
- attribute_select(options, html_options, Constants::SORT) +
86
+ attribute_select(options, html_options, 'sort'.freeze) +
76
87
  sort_direction_select(options, html_options)
77
88
  end
78
89
 
@@ -84,6 +95,10 @@ module Ransack
84
95
  @template.sort_link @object, attribute, *args
85
96
  end
86
97
 
98
+ def sort_url(attribute, *args)
99
+ @template.sort_url @object, attribute, *args
100
+ end
101
+
87
102
  def condition_fields(*args, &block)
88
103
  search_fields(:c, args, block)
89
104
  end
@@ -135,7 +150,7 @@ module Ransack
135
150
  else
136
151
  only = Array.wrap(only).map(&:to_s)
137
152
  keys = keys.select {
138
- |k| only.include? k.sub(/_(any|all)$/, Constants::EMPTY)
153
+ |k| only.include? k.sub(/_(any|all)$/, ''.freeze)
139
154
  }
140
155
  end
141
156
  end
@@ -177,9 +192,9 @@ module Ransack
177
192
 
178
193
  def sort_array
179
194
  [
180
- [Constants::ASC, object.translate(Constants::ASC)],
181
- [Constants::DESC, object.translate(Constants::DESC)]
182
- ]
195
+ ['asc'.freeze, object.translate('asc'.freeze)].freeze,
196
+ ['desc'.freeze, object.translate('desc'.freeze)].freeze
197
+ ].freeze
183
198
  end
184
199
 
185
200
  def combinator_choices
@@ -234,7 +249,7 @@ module Ransack
234
249
  Translate.association(base, :context => object.context),
235
250
  collection_for_base(action, base)
236
251
  ]
237
- rescue UntraversableAssociationError => e
252
+ rescue UntraversableAssociationError
238
253
  nil
239
254
  end
240
255
  end