mini-fast-sys 0.0.1

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 (94) hide show
  1. checksums.yaml +7 -0
  2. data/mini-fast-sys.gemspec +12 -0
  3. data/ransack-4.4.1/LICENSE +20 -0
  4. data/ransack-4.4.1/README.md +101 -0
  5. data/ransack-4.4.1/lib/polyamorous/activerecord/join_association.rb +70 -0
  6. data/ransack-4.4.1/lib/polyamorous/activerecord/join_association_7_2.rb +55 -0
  7. data/ransack-4.4.1/lib/polyamorous/activerecord/join_dependency.rb +102 -0
  8. data/ransack-4.4.1/lib/polyamorous/activerecord/reflection.rb +11 -0
  9. data/ransack-4.4.1/lib/polyamorous/join.rb +70 -0
  10. data/ransack-4.4.1/lib/polyamorous/polyamorous.rb +27 -0
  11. data/ransack-4.4.1/lib/polyamorous/swapping_reflection_class.rb +11 -0
  12. data/ransack-4.4.1/lib/polyamorous/tree_node.rb +7 -0
  13. data/ransack-4.4.1/lib/ransack/active_record.rb +14 -0
  14. data/ransack-4.4.1/lib/ransack/adapters/active_record/base.rb +152 -0
  15. data/ransack-4.4.1/lib/ransack/adapters/active_record/context.rb +373 -0
  16. data/ransack-4.4.1/lib/ransack/configuration.rb +209 -0
  17. data/ransack-4.4.1/lib/ransack/constants.rb +176 -0
  18. data/ransack-4.4.1/lib/ransack/context.rb +190 -0
  19. data/ransack-4.4.1/lib/ransack/helpers/form_builder.rb +277 -0
  20. data/ransack-4.4.1/lib/ransack/helpers/form_helper.rb +311 -0
  21. data/ransack-4.4.1/lib/ransack/helpers.rb +2 -0
  22. data/ransack-4.4.1/lib/ransack/invalid_search_error.rb +3 -0
  23. data/ransack-4.4.1/lib/ransack/locale/ar.yml +70 -0
  24. data/ransack-4.4.1/lib/ransack/locale/az.yml +70 -0
  25. data/ransack-4.4.1/lib/ransack/locale/bg.yml +70 -0
  26. data/ransack-4.4.1/lib/ransack/locale/ca.yml +70 -0
  27. data/ransack-4.4.1/lib/ransack/locale/cs.yml +70 -0
  28. data/ransack-4.4.1/lib/ransack/locale/da.yml +70 -0
  29. data/ransack-4.4.1/lib/ransack/locale/de.yml +70 -0
  30. data/ransack-4.4.1/lib/ransack/locale/el.yml +70 -0
  31. data/ransack-4.4.1/lib/ransack/locale/en.yml +70 -0
  32. data/ransack-4.4.1/lib/ransack/locale/es.yml +70 -0
  33. data/ransack-4.4.1/lib/ransack/locale/fa.yml +70 -0
  34. data/ransack-4.4.1/lib/ransack/locale/fi.yml +71 -0
  35. data/ransack-4.4.1/lib/ransack/locale/fr.yml +70 -0
  36. data/ransack-4.4.1/lib/ransack/locale/hu.yml +70 -0
  37. data/ransack-4.4.1/lib/ransack/locale/id.yml +70 -0
  38. data/ransack-4.4.1/lib/ransack/locale/it.yml +70 -0
  39. data/ransack-4.4.1/lib/ransack/locale/ja.yml +70 -0
  40. data/ransack-4.4.1/lib/ransack/locale/ko.yml +70 -0
  41. data/ransack-4.4.1/lib/ransack/locale/nl.yml +70 -0
  42. data/ransack-4.4.1/lib/ransack/locale/pt-BR.yml +70 -0
  43. data/ransack-4.4.1/lib/ransack/locale/ro.yml +70 -0
  44. data/ransack-4.4.1/lib/ransack/locale/ru.yml +70 -0
  45. data/ransack-4.4.1/lib/ransack/locale/sk.yml +70 -0
  46. data/ransack-4.4.1/lib/ransack/locale/sv.yml +70 -0
  47. data/ransack-4.4.1/lib/ransack/locale/tr.yml +70 -0
  48. data/ransack-4.4.1/lib/ransack/locale/uk.yml +72 -0
  49. data/ransack-4.4.1/lib/ransack/locale/zh-CN.yml +70 -0
  50. data/ransack-4.4.1/lib/ransack/locale/zh-TW.yml +70 -0
  51. data/ransack-4.4.1/lib/ransack/naming.rb +58 -0
  52. data/ransack-4.4.1/lib/ransack/nodes/attribute.rb +59 -0
  53. data/ransack-4.4.1/lib/ransack/nodes/bindable.rb +52 -0
  54. data/ransack-4.4.1/lib/ransack/nodes/condition.rb +399 -0
  55. data/ransack-4.4.1/lib/ransack/nodes/grouping.rb +206 -0
  56. data/ransack-4.4.1/lib/ransack/nodes/node.rb +34 -0
  57. data/ransack-4.4.1/lib/ransack/nodes/sort.rb +54 -0
  58. data/ransack-4.4.1/lib/ransack/nodes/value.rb +115 -0
  59. data/ransack-4.4.1/lib/ransack/predicate.rb +75 -0
  60. data/ransack-4.4.1/lib/ransack/ransacker.rb +24 -0
  61. data/ransack-4.4.1/lib/ransack/search.rb +195 -0
  62. data/ransack-4.4.1/lib/ransack/translate.rb +156 -0
  63. data/ransack-4.4.1/lib/ransack/version.rb +3 -0
  64. data/ransack-4.4.1/lib/ransack/visitor.rb +87 -0
  65. data/ransack-4.4.1/lib/ransack.rb +33 -0
  66. data/ransack-4.4.1/spec/console.rb +13 -0
  67. data/ransack-4.4.1/spec/factories/articles.rb +7 -0
  68. data/ransack-4.4.1/spec/factories/comments.rb +7 -0
  69. data/ransack-4.4.1/spec/factories/notes.rb +13 -0
  70. data/ransack-4.4.1/spec/factories/people.rb +10 -0
  71. data/ransack-4.4.1/spec/factories/tags.rb +5 -0
  72. data/ransack-4.4.1/spec/helpers/polyamorous_helper.rb +13 -0
  73. data/ransack-4.4.1/spec/helpers/ransack_helper.rb +9 -0
  74. data/ransack-4.4.1/spec/polyamorous/activerecord_compatibility_spec.rb +15 -0
  75. data/ransack-4.4.1/spec/polyamorous/join_association_spec.rb +29 -0
  76. data/ransack-4.4.1/spec/polyamorous/join_dependency_spec.rb +80 -0
  77. data/ransack-4.4.1/spec/polyamorous/join_spec.rb +19 -0
  78. data/ransack-4.4.1/spec/ransack/adapters/active_record/base_spec.rb +943 -0
  79. data/ransack-4.4.1/spec/ransack/adapters/active_record/context_spec.rb +219 -0
  80. data/ransack-4.4.1/spec/ransack/configuration_spec.rb +201 -0
  81. data/ransack-4.4.1/spec/ransack/helpers/form_builder_spec.rb +169 -0
  82. data/ransack-4.4.1/spec/ransack/helpers/form_helper_spec.rb +1075 -0
  83. data/ransack-4.4.1/spec/ransack/invalid_search_error_spec.rb +27 -0
  84. data/ransack-4.4.1/spec/ransack/nodes/condition_spec.rb +333 -0
  85. data/ransack-4.4.1/spec/ransack/nodes/grouping_spec.rb +111 -0
  86. data/ransack-4.4.1/spec/ransack/nodes/value_spec.rb +126 -0
  87. data/ransack-4.4.1/spec/ransack/predicate_spec.rb +504 -0
  88. data/ransack-4.4.1/spec/ransack/ransacker_spec.rb +69 -0
  89. data/ransack-4.4.1/spec/ransack/search_spec.rb +821 -0
  90. data/ransack-4.4.1/spec/ransack/translate_spec.rb +16 -0
  91. data/ransack-4.4.1/spec/spec_helper.rb +52 -0
  92. data/ransack-4.4.1/spec/support/en.yml +18 -0
  93. data/ransack-4.4.1/spec/support/schema.rb +419 -0
  94. metadata +133 -0
@@ -0,0 +1,115 @@
1
+ module Ransack
2
+ module Nodes
3
+ class Value < Node
4
+ attr_accessor :value
5
+ delegate :present?, :blank?, to: :value
6
+
7
+ def initialize(context, value = nil)
8
+ super(context)
9
+ @value = value
10
+ end
11
+
12
+ def persisted?
13
+ false
14
+ end
15
+
16
+ def eql?(other)
17
+ self.class == other.class && self.value == other.value
18
+ end
19
+ alias :== :eql?
20
+
21
+ def hash
22
+ value.hash
23
+ end
24
+
25
+ def cast(type)
26
+ case type
27
+ when :date
28
+ cast_to_date(value)
29
+ when :datetime, :timestamp, :time, :timestamptz
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
45
+
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
56
+
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
67
+
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
77
+
78
+ def cast_to_string(val)
79
+ val.respond_to?(:to_s) ? val.to_s : String.new(val)
80
+ end
81
+
82
+ def cast_to_integer(val)
83
+ val.respond_to?(:to_i) && !val.blank? ? val.to_i : nil
84
+ end
85
+
86
+ def cast_to_float(val)
87
+ val.blank? ? nil : val.to_f
88
+ end
89
+
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
99
+ end
100
+ end
101
+
102
+ def cast_to_money(val)
103
+ val.blank? ? nil : val.to_f.to_s
104
+ end
105
+
106
+ def inspect
107
+ "Value <#{value}>"
108
+ end
109
+
110
+ def array_of_arrays?(val)
111
+ Array === val && Array === val.first
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,75 @@
1
+ module Ransack
2
+ class Predicate
3
+ attr_reader :name, :arel_predicate, :type, :formatter, :validator,
4
+ :compound, :wants_array, :case_insensitive
5
+
6
+ class << self
7
+
8
+ def names
9
+ Ransack.predicates.keys
10
+ end
11
+
12
+ def named(name)
13
+ Ransack.predicates[(name || Ransack.options[:default_predicate]).to_s]
14
+ end
15
+
16
+ def detect_and_strip_from_string!(str)
17
+ detect_from_string str, chomp: true
18
+ end
19
+
20
+ def detect_from_string(str, chomp: false)
21
+ return unless str
22
+
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
29
+
30
+ nil
31
+ end
32
+
33
+ end
34
+
35
+ def initialize(opts = {})
36
+ @name = opts[:name]
37
+ @arel_predicate = opts[:arel_predicate]
38
+ @type = opts[:type]
39
+ @formatter = opts[:formatter]
40
+ @validator = opts[:validator] ||
41
+ lambda { |v| v.respond_to?(:empty?) ? !v.empty? : !v.nil? }
42
+ @compound = opts[:compound]
43
+ @wants_array = opts.fetch(:wants_array,
44
+ @compound || Constants::IN_NOT_IN.include?(@arel_predicate))
45
+ @case_insensitive = opts[:case_insensitive]
46
+ end
47
+
48
+ def eql?(other)
49
+ self.class == other.class &&
50
+ self.name == other.name
51
+ end
52
+ alias :== :eql?
53
+
54
+ def hash
55
+ name.hash
56
+ end
57
+
58
+ def format(val)
59
+ if formatter
60
+ formatter.call(val)
61
+ else
62
+ val
63
+ end
64
+ end
65
+
66
+ def validate(vals, type = @type)
67
+ vals.any? { |v| validator.call(type ? v.cast(type) : v.value) }
68
+ end
69
+
70
+ def negative?
71
+ @name.include?("not_".freeze)
72
+ end
73
+
74
+ end
75
+ end
@@ -0,0 +1,24 @@
1
+ module Ransack
2
+ class Ransacker
3
+
4
+ attr_reader :name, :type, :formatter, :args
5
+
6
+ delegate :call, to: :@callable
7
+
8
+ def initialize(klass, name, opts = {}, &block)
9
+ @klass, @name = klass, name
10
+
11
+ @type = opts[:type] || :string
12
+ @args = opts[:args] || [:parent]
13
+ @formatter = opts[:formatter]
14
+ @callable = opts[:callable] || block ||
15
+ (@klass.method(name) if @klass.respond_to?(name)) ||
16
+ proc { |parent| parent.table[name] }
17
+ end
18
+
19
+ def attr_from(bindable)
20
+ call(*args.map { |arg| bindable.send(arg) })
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,195 @@
1
+ require 'ransack/nodes/bindable'
2
+ require 'ransack/nodes/node'
3
+ require 'ransack/nodes/attribute'
4
+ require 'ransack/nodes/value'
5
+ require 'ransack/nodes/condition'
6
+ require 'ransack/nodes/sort'
7
+ require 'ransack/nodes/grouping'
8
+ require 'ransack/context'
9
+ require 'ransack/naming'
10
+ require 'ransack/invalid_search_error'
11
+
12
+ module Ransack
13
+ class Search
14
+ include Naming
15
+
16
+ attr_reader :base, :context
17
+
18
+ delegate :object, :klass, to: :context
19
+ delegate :new_grouping, :new_condition,
20
+ :build_grouping, :build_condition,
21
+ :translate, to: :base
22
+
23
+ def initialize(object, params = {}, options = {})
24
+ strip_whitespace = options.fetch(:strip_whitespace, Ransack.options[:strip_whitespace])
25
+ params = params.to_unsafe_h if params.respond_to?(:to_unsafe_h)
26
+ if params.is_a? Hash
27
+ params = params.dup
28
+ params = params.transform_values { |v| v.is_a?(String) && strip_whitespace ? v.strip : v }
29
+ params.delete_if { |k, v| [*v].all?{ |i| i.blank? && i != false } }
30
+ else
31
+ params = {}
32
+ end
33
+ @context = options[:context] || Context.for(object, options)
34
+ @context.auth_object = options[:auth_object]
35
+ @base = Nodes::Grouping.new(
36
+ @context, options[:grouping] || Constants::AND
37
+ )
38
+ @scope_args = {}
39
+ @sorts ||= []
40
+ @ignore_unknown_conditions = options[:ignore_unknown_conditions] == false ? false : true
41
+ build(params.with_indifferent_access)
42
+ end
43
+
44
+ def result(opts = {})
45
+ @context.evaluate(self, opts)
46
+ end
47
+
48
+ def build(params)
49
+ collapse_multiparameter_attributes!(params).each do |key, value|
50
+ if ['s'.freeze, 'sorts'.freeze].freeze.include?(key)
51
+ send("#{key}=", value)
52
+ elsif @context.ransackable_scope?(key, @context.object)
53
+ add_scope(key, value)
54
+ elsif base.attribute_method?(key)
55
+ base.send("#{key}=", value)
56
+ elsif !Ransack.options[:ignore_unknown_conditions] || !@ignore_unknown_conditions
57
+ raise InvalidSearchError, "Invalid search term #{key}"
58
+ end
59
+ end
60
+ self
61
+ end
62
+
63
+ def sorts=(args)
64
+ case args
65
+ when Array
66
+ args.each do |sort|
67
+ if sort.kind_of? Hash
68
+ sort = Nodes::Sort.new(@context).build(sort)
69
+ else
70
+ sort = Nodes::Sort.extract(@context, sort)
71
+ end
72
+ self.sorts << sort if sort
73
+ end
74
+ when Hash
75
+ args.each do |index, attrs|
76
+ sort = Nodes::Sort.new(@context).build(attrs)
77
+ self.sorts << sort
78
+ end
79
+ when String
80
+ self.sorts = [args]
81
+ else
82
+ raise InvalidSearchError,
83
+ "Invalid argument (#{args.class}) supplied to sorts="
84
+ end
85
+ end
86
+ alias :s= :sorts=
87
+
88
+ def sorts
89
+ @sorts
90
+ end
91
+ alias :s :sorts
92
+
93
+ def build_sort(opts = {})
94
+ new_sort(opts).tap do |sort|
95
+ self.sorts << sort
96
+ end
97
+ end
98
+
99
+ def new_sort(opts = {})
100
+ Nodes::Sort.new(@context).build(opts)
101
+ end
102
+
103
+ def method_missing(method_id, *args)
104
+ method_name = method_id.to_s
105
+ getter_name = method_name.sub(/=$/, ''.freeze)
106
+ if base.attribute_method?(getter_name)
107
+ base.send(method_id, *args)
108
+ elsif @context.ransackable_scope?(getter_name, @context.object)
109
+ if method_name =~ /=$/
110
+ add_scope getter_name, args
111
+ else
112
+ @scope_args[method_name]
113
+ end
114
+ else
115
+ super
116
+ end
117
+ end
118
+
119
+ def inspect
120
+ details = [
121
+ [:class, klass.name],
122
+ ([:scope, @scope_args] if @scope_args.present?),
123
+ [:base, base.inspect]
124
+ ]
125
+ .compact
126
+ .map { |d| d.join(': '.freeze) }
127
+ .join(', '.freeze)
128
+
129
+ "Ransack::Search<#{details}>"
130
+ end
131
+
132
+ private
133
+
134
+ def add_scope(key, args)
135
+ sanitized_args = if Ransack.options[:sanitize_scope_args] && !@context.ransackable_scope_skip_sanitize_args?(key, @context.object)
136
+ sanitized_scope_args(args)
137
+ else
138
+ args
139
+ end
140
+
141
+ if @context.scope_arity(key) == 1
142
+ @scope_args[key] = args.is_a?(Array) ? args[0] : args
143
+ else
144
+ @scope_args[key] = args.is_a?(Array) ? sanitized_args : args
145
+ end
146
+ @context.chain_scope(key, sanitized_args)
147
+ end
148
+
149
+ def sanitized_scope_args(args)
150
+ if args.is_a?(Array)
151
+ args = args.map(&method(:sanitized_scope_args))
152
+ end
153
+
154
+ if Constants::TRUE_VALUES.include? args
155
+ true
156
+ elsif Constants::FALSE_VALUES.include? args
157
+ false
158
+ else
159
+ args
160
+ end
161
+ end
162
+
163
+ def collapse_multiparameter_attributes!(attrs)
164
+ attrs.keys.each do |k|
165
+ if k.include?(Constants::LEFT_PARENTHESIS)
166
+ real_attribute, position = k.split(/\(|\)/)
167
+ cast =
168
+ if Constants::A_S_I.include?(position.last)
169
+ position.last
170
+ else
171
+ nil
172
+ end
173
+ position = position.to_i - 1
174
+ value = attrs.delete(k)
175
+ attrs[real_attribute] ||= []
176
+ attrs[real_attribute][position] =
177
+ if cast
178
+ if value.blank? && cast == Constants::I
179
+ nil
180
+ else
181
+ value.send("to_#{cast}")
182
+ end
183
+ else
184
+ value
185
+ end
186
+ elsif Hash === attrs[k]
187
+ collapse_multiparameter_attributes!(attrs[k])
188
+ end
189
+ end
190
+
191
+ attrs
192
+ end
193
+
194
+ end
195
+ end
@@ -0,0 +1,156 @@
1
+ require 'i18n'
2
+
3
+ I18n.load_path += Dir[
4
+ File.join(File.dirname(__FILE__), 'locale'.freeze, '*.yml'.freeze)
5
+ ]
6
+
7
+ module Ransack
8
+ module Translate
9
+ class << self
10
+ def word(key, options = {})
11
+ I18n.translate(:"ransack.#{key}", default: key.to_s)
12
+ end
13
+
14
+ def predicate(key, options = {})
15
+ I18n.translate(:"ransack.predicates.#{key}", default: key.to_s)
16
+ end
17
+
18
+ def attribute(key, options = {})
19
+ unless context = options.delete(:context)
20
+ raise ArgumentError, "A context is required to translate attributes"
21
+ end
22
+
23
+ original_name = key.to_s
24
+ base_class = context.klass
25
+ base_ancestors = base_class.ancestors.select {
26
+ |x| x.respond_to?(:model_name)
27
+ }
28
+ attributes_str = original_name.dup # will be modified by ⬇
29
+ predicate = Predicate.detect_and_strip_from_string!(attributes_str)
30
+ attribute_names = attributes_str.split(/_and_|_or_/)
31
+ combinator = attributes_str =~ /_and_/ ? :and : :or
32
+ defaults = base_ancestors.map do |klass|
33
+ "ransack.attributes.#{i18n_key(klass)}.#{original_name}".to_sym
34
+ end
35
+ defaults << options.delete(:default) if options[:default]
36
+
37
+ translated_names = attribute_names.map do |name|
38
+ attribute_name(context, name, options[:include_associations])
39
+ end
40
+
41
+ interpolations = {
42
+ attributes: translated_names.join(" #{Translate.word(combinator)} ")
43
+ }
44
+
45
+ if predicate
46
+ defaults << "%{attributes} %{predicate}".freeze
47
+ interpolations[:predicate] = Translate.predicate(predicate)
48
+ else
49
+ defaults << "%{attributes}".freeze
50
+ end
51
+
52
+ options.reverse_merge! count: 1, default: defaults
53
+ I18n.translate(defaults.shift, **options.merge(interpolations))
54
+ end
55
+
56
+ def association(key, options = {})
57
+ unless context = options.delete(:context)
58
+ raise ArgumentError, "A context is required to translate associations"
59
+ end
60
+
61
+ defaults =
62
+ if key.blank?
63
+ [:"ransack.models.#{i18n_key(context.klass)}",
64
+ :"#{context.klass.i18n_scope}.models.#{i18n_key(context.klass)}"]
65
+ else
66
+ [:"ransack.associations.#{i18n_key(context.klass)}.#{key}"]
67
+ end
68
+ defaults << context.traverse(key).model_name.human
69
+ options = { count: 1, default: defaults }
70
+ I18n.translate(defaults.shift, **options)
71
+ end
72
+
73
+ private
74
+
75
+ def attribute_name(context, name, include_associations = nil)
76
+ @context, @name = context, name
77
+ @assoc_path = context.association_path(name)
78
+ @attr_name = @name.sub(/^#{@assoc_path}_/, ''.freeze)
79
+ associated_class = @context.traverse(@assoc_path) if @assoc_path.present?
80
+ @include_associated = include_associations && associated_class
81
+
82
+ defaults = default_attribute_name << fallback_args
83
+ options = { count: 1, default: defaults }
84
+ interpolations = build_interpolations(associated_class)
85
+
86
+ I18n.translate(defaults.shift, **options.merge(interpolations))
87
+ end
88
+
89
+ def default_attribute_name
90
+ ["ransack.attributes.#{i18n_key(@context.klass)}.#{@name}".to_sym]
91
+ end
92
+
93
+ def fallback_args
94
+ if @include_associated
95
+ '%{association_name} %{attr_fallback_name}'.freeze
96
+ else
97
+ '%{attr_fallback_name}'.freeze
98
+ end
99
+ end
100
+
101
+ def build_interpolations(associated_class)
102
+ {
103
+ attr_fallback_name: attr_fallback_name(associated_class),
104
+ association_name: association_name
105
+ }.reject { |_, value| value.nil? }
106
+ end
107
+
108
+ def attr_fallback_name(associated_class)
109
+ I18n.t(
110
+ :"ransack.attributes.#{fallback_class(associated_class)}.#{@attr_name}",
111
+ default: default_interpolation(associated_class)
112
+ )
113
+ end
114
+
115
+ def fallback_class(associated_class)
116
+ i18n_key(associated_class || @context.klass)
117
+ end
118
+
119
+ def association_name
120
+ association(@assoc_path, context: @context) if @include_associated
121
+ end
122
+
123
+ def default_interpolation(associated_class)
124
+ [
125
+ associated_attribute(associated_class),
126
+ ".attributes.#{@attr_name}".to_sym,
127
+ @attr_name.humanize
128
+ ].flatten
129
+ end
130
+
131
+ def associated_attribute(associated_class)
132
+ if associated_class
133
+ translated_attribute(associated_class)
134
+ else
135
+ translated_ancestor_attributes
136
+ end
137
+ end
138
+
139
+ def translated_attribute(associated_class)
140
+ key = "#{associated_class.i18n_scope}.attributes.#{
141
+ i18n_key(associated_class)}.#{@attr_name}"
142
+ ["#{key}.one".to_sym, key.to_sym]
143
+ end
144
+
145
+ def translated_ancestor_attributes
146
+ @context.klass.ancestors
147
+ .select { |ancestor| ancestor.respond_to?(:model_name) }
148
+ .map { |ancestor| translated_attribute(ancestor) }
149
+ end
150
+
151
+ def i18n_key(klass)
152
+ klass.model_name.i18n_key
153
+ end
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,3 @@
1
+ module Ransack
2
+ VERSION = '4.4.1'
3
+ end
@@ -0,0 +1,87 @@
1
+ module Ransack
2
+ class Visitor
3
+
4
+ def accept(object)
5
+ visit(object)
6
+ end
7
+
8
+ def can_accept?(object)
9
+ respond_to? DISPATCH[object.class]
10
+ end
11
+
12
+ def visit_Array(object)
13
+ object.map { |o| accept(o) }.compact
14
+ end
15
+
16
+ def visit_Ransack_Nodes_Condition(object)
17
+ object.arel_predicate if object.valid?
18
+ end
19
+
20
+ def visit_Ransack_Nodes_Grouping(object)
21
+ if object.combinator == Constants::OR
22
+ visit_or(object)
23
+ else
24
+ visit_and(object)
25
+ end
26
+ end
27
+
28
+ def visit_and(object)
29
+ nodes = object.values.map { |o| accept(o) }.compact
30
+ return nil unless nodes.size > 0
31
+
32
+ if nodes.size > 1
33
+ Arel::Nodes::Grouping.new(Arel::Nodes::And.new(nodes))
34
+ else
35
+ nodes.first
36
+ end
37
+ end
38
+
39
+ def visit_or(object)
40
+ nodes = object.values.map { |o| accept(o) }.compact
41
+ nodes.inject(&:or)
42
+ end
43
+
44
+ def quoted?(object)
45
+ case object
46
+ when Arel::Nodes::SqlLiteral, Bignum, Fixnum
47
+ false
48
+ else
49
+ true
50
+ end
51
+ end
52
+
53
+ def visit(object)
54
+ send(DISPATCH[object.class], object)
55
+ end
56
+
57
+ def visit_Ransack_Nodes_Sort(object)
58
+ if object.valid?
59
+ if object.attr.is_a?(Arel::Attributes::Attribute)
60
+ object.attr.send(object.dir)
61
+ else
62
+ ordered(object)
63
+ end
64
+ else
65
+ scope_name = :"sort_by_#{object.name}_#{object.dir}"
66
+ scope_name if object.context.object.respond_to?(scope_name)
67
+ end
68
+ end
69
+
70
+ DISPATCH = Hash.new do |hash, klass|
71
+ hash[klass] = "visit_#{
72
+ klass.name.gsub(Constants::TWO_COLONS, Constants::UNDERSCORE)
73
+ }"
74
+ end
75
+
76
+ private
77
+
78
+ def ordered(object)
79
+ case object.dir
80
+ when 'asc'.freeze
81
+ Arel::Nodes::Ascending.new(object.attr)
82
+ when 'desc'.freeze
83
+ Arel::Nodes::Descending.new(object.attr)
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,33 @@
1
+ require 'active_support/dependencies/autoload'
2
+ require 'active_support/deprecation'
3
+ require 'active_support/deprecator'
4
+
5
+ require 'active_support/core_ext'
6
+ require 'ransack/configuration'
7
+ require 'polyamorous/polyamorous'
8
+
9
+ module Ransack
10
+ extend Configuration
11
+ class UntraversableAssociationError < StandardError; end
12
+ end
13
+
14
+ Ransack.configure do |config|
15
+ Ransack::Constants::AREL_PREDICATES.each do |name|
16
+ config.add_predicate name, arel_predicate: name
17
+ end
18
+ Ransack::Constants::DERIVED_PREDICATES.each do |args|
19
+ config.add_predicate(*args)
20
+ end
21
+ end
22
+
23
+ require 'ransack/search'
24
+ require 'ransack/ransacker'
25
+ require 'ransack/translate'
26
+ require 'ransack/active_record'
27
+ require 'ransack/context'
28
+ require 'ransack/version'
29
+
30
+ ActiveSupport.on_load(:action_controller) do
31
+ require 'ransack/helpers'
32
+ ActionController::Base.helper Ransack::Helpers::FormHelper
33
+ end
@@ -0,0 +1,13 @@
1
+ Bundler.setup
2
+ require 'factory_bot'
3
+ require 'faker'
4
+ require 'ransack'
5
+
6
+ Dir[File.expand_path('../../spec/{helpers,support,factories}/*.rb', __FILE__)]
7
+ .each do |f|
8
+ require f
9
+ end
10
+
11
+ Faker::Config.random = Random.new(0)
12
+
13
+ Schema.create