ransack 1.8.3 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +3 -0
- data/.travis.yml +26 -63
- data/CHANGELOG.md +187 -24
- data/CONTRIBUTING.md +9 -0
- data/Gemfile +5 -20
- data/README.md +163 -40
- data/Rakefile +1 -22
- data/lib/ransack/adapters/active_record/base.rb +11 -2
- data/lib/ransack/adapters/active_record/context.rb +178 -168
- data/lib/ransack/adapters/active_record/ransack/constants.rb +6 -3
- data/lib/ransack/adapters/active_record/ransack/context.rb +10 -16
- data/lib/ransack/adapters/active_record/ransack/nodes/condition.rb +3 -3
- data/lib/ransack/adapters/active_record/ransack/translate.rb +1 -5
- data/lib/ransack/adapters/active_record/ransack/visitor.rb +23 -0
- data/lib/ransack/adapters/active_record.rb +0 -9
- data/lib/ransack/adapters.rb +2 -0
- data/lib/ransack/configuration.rb +30 -4
- data/lib/ransack/constants.rb +4 -1
- data/lib/ransack/context.rb +29 -24
- data/lib/ransack/helpers/form_builder.rb +15 -3
- data/lib/ransack/helpers/form_helper.rb +8 -3
- data/lib/ransack/locale/ar.yml +70 -0
- data/lib/ransack/locale/az.yml +70 -0
- data/lib/ransack/locale/bg.yml +70 -0
- data/lib/ransack/locale/ca.yml +70 -0
- data/lib/ransack/locale/el.yml +70 -0
- data/lib/ransack/locale/es.yml +22 -22
- data/lib/ransack/locale/fa.yml +70 -0
- data/lib/ransack/locale/fi.yml +71 -0
- data/lib/ransack/locale/it.yml +70 -0
- data/lib/ransack/locale/nl.yml +4 -4
- data/lib/ransack/locale/ru.yml +70 -0
- data/lib/ransack/locale/tr.yml +70 -0
- data/lib/ransack/locale/zh-CN.yml +12 -12
- data/lib/ransack/nodes/attribute.rb +1 -1
- data/lib/ransack/nodes/grouping.rb +2 -7
- data/lib/ransack/nodes/value.rb +74 -68
- data/lib/ransack/predicate.rb +11 -19
- data/lib/ransack/search.rb +1 -1
- data/lib/ransack/translate.rb +115 -115
- data/lib/ransack/version.rb +1 -1
- data/lib/ransack/visitor.rb +1 -12
- data/lib/ransack.rb +5 -2
- data/logo/ransack-h.png +0 -0
- data/logo/ransack-h.svg +34 -0
- data/logo/ransack-v.png +0 -0
- data/logo/ransack-v.svg +34 -0
- data/logo/ransack.png +0 -0
- data/logo/ransack.svg +21 -0
- data/polyamorous/lib/polyamorous/activerecord_5.0_ruby_2/join_association.rb +2 -0
- data/polyamorous/lib/polyamorous/activerecord_5.0_ruby_2/join_dependency.rb +2 -0
- data/polyamorous/lib/polyamorous/activerecord_5.1_ruby_2/join_association.rb +31 -0
- data/polyamorous/lib/polyamorous/activerecord_5.1_ruby_2/join_dependency.rb +112 -0
- data/polyamorous/lib/polyamorous/activerecord_5.2.0_ruby_2/join_association.rb +31 -0
- data/polyamorous/lib/polyamorous/activerecord_5.2.0_ruby_2/join_dependency.rb +112 -0
- data/polyamorous/lib/polyamorous/activerecord_5.2.0_ruby_2/reflection.rb +12 -0
- data/polyamorous/lib/polyamorous/activerecord_5.2.1_ruby_2/join_association.rb +22 -0
- data/polyamorous/lib/polyamorous/activerecord_5.2.1_ruby_2/join_dependency.rb +81 -0
- data/polyamorous/lib/polyamorous/activerecord_5.2.1_ruby_2/reflection.rb +2 -0
- data/polyamorous/lib/polyamorous/activerecord_6.0_ruby_2/join_association.rb +2 -0
- data/polyamorous/lib/polyamorous/activerecord_6.0_ruby_2/join_dependency.rb +81 -0
- data/polyamorous/lib/polyamorous/activerecord_6.0_ruby_2/reflection.rb +2 -0
- data/polyamorous/lib/polyamorous/activerecord_6.1_ruby_2/join_association.rb +2 -0
- data/polyamorous/lib/polyamorous/activerecord_6.1_ruby_2/join_dependency.rb +2 -0
- data/polyamorous/lib/polyamorous/activerecord_6.1_ruby_2/reflection.rb +2 -0
- data/polyamorous/lib/polyamorous/join.rb +70 -0
- data/polyamorous/lib/polyamorous/swapping_reflection_class.rb +11 -0
- data/polyamorous/lib/polyamorous/tree_node.rb +7 -0
- data/polyamorous/lib/polyamorous/version.rb +3 -0
- data/polyamorous/lib/polyamorous.rb +29 -0
- data/polyamorous/polyamorous.gemspec +35 -0
- data/ransack.gemspec +9 -10
- data/spec/helpers/polyamorous_helper.rb +28 -0
- data/spec/ransack/adapters/active_record/base_spec.rb +74 -0
- data/spec/ransack/adapters/active_record/context_spec.rb +44 -6
- data/spec/ransack/configuration_spec.rb +17 -2
- data/spec/ransack/helpers/form_builder_spec.rb +3 -15
- data/spec/ransack/helpers/form_helper_spec.rb +88 -151
- data/spec/ransack/join_association_spec.rb +28 -0
- data/spec/ransack/join_dependency_spec.rb +97 -0
- data/spec/ransack/join_spec.rb +19 -0
- data/spec/ransack/predicate_spec.rb +16 -2
- data/spec/ransack/search_spec.rb +32 -3
- data/spec/spec_helper.rb +5 -0
- data/spec/support/schema.rb +45 -21
- metadata +81 -67
- data/lib/ransack/adapters/active_record/3.0/compat.rb +0 -179
- data/lib/ransack/adapters/active_record/3.0/context.rb +0 -203
- data/lib/ransack/adapters/active_record/3.1/context.rb +0 -212
- data/lib/ransack/adapters/active_record/3.2/context.rb +0 -44
- data/lib/ransack/adapters/active_record/compat.rb +0 -14
- data/lib/ransack/adapters/mongoid/3.2/.gitkeep +0 -0
- data/lib/ransack/adapters/mongoid/attributes/attribute.rb +0 -37
- data/lib/ransack/adapters/mongoid/attributes/order_predications.rb +0 -17
- data/lib/ransack/adapters/mongoid/attributes/predications.rb +0 -141
- data/lib/ransack/adapters/mongoid/base.rb +0 -134
- data/lib/ransack/adapters/mongoid/context.rb +0 -212
- data/lib/ransack/adapters/mongoid/inquiry_hash.rb +0 -23
- data/lib/ransack/adapters/mongoid/ransack/constants.rb +0 -88
- data/lib/ransack/adapters/mongoid/ransack/context.rb +0 -60
- data/lib/ransack/adapters/mongoid/ransack/nodes/condition.rb +0 -27
- data/lib/ransack/adapters/mongoid/ransack/translate.rb +0 -13
- data/lib/ransack/adapters/mongoid/ransack/visitor.rb +0 -24
- data/lib/ransack/adapters/mongoid/table.rb +0 -35
- data/lib/ransack/adapters/mongoid.rb +0 -15
- data/spec/mongoid/adapters/mongoid/base_spec.rb +0 -314
- data/spec/mongoid/adapters/mongoid/context_spec.rb +0 -56
- data/spec/mongoid/configuration_spec.rb +0 -162
- data/spec/mongoid/dependencies_spec.rb +0 -8
- data/spec/mongoid/helpers/ransack_helper.rb +0 -11
- data/spec/mongoid/nodes/condition_spec.rb +0 -49
- data/spec/mongoid/nodes/grouping_spec.rb +0 -13
- data/spec/mongoid/predicate_spec.rb +0 -155
- data/spec/mongoid/search_spec.rb +0 -445
- data/spec/mongoid/support/mongoid.yml +0 -11
- data/spec/mongoid/support/schema.rb +0 -135
- data/spec/mongoid/translate_spec.rb +0 -14
- data/spec/mongoid_spec_helper.rb +0 -63
- data/spec/ransack/dependencies_spec.rb +0 -12
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'ransack/context'
|
2
|
-
require 'ransack/adapters/active_record/compat'
|
3
2
|
require 'polyamorous'
|
4
3
|
|
5
4
|
module Ransack
|
@@ -7,14 +6,11 @@ module Ransack
|
|
7
6
|
module ActiveRecord
|
8
7
|
class Context < ::Ransack::Context
|
9
8
|
|
10
|
-
# Because the AR::Associations namespace is insane
|
11
|
-
if defined? ::ActiveRecord::Associations::JoinDependency
|
12
|
-
JoinDependency = ::ActiveRecord::Associations::JoinDependency
|
13
|
-
end
|
14
|
-
|
15
9
|
def initialize(object, options = {})
|
16
10
|
super
|
17
|
-
|
11
|
+
if ::ActiveRecord::VERSION::STRING < Constants::RAILS_5_2
|
12
|
+
@arel_visitor = @engine.connection.visitor
|
13
|
+
end
|
18
14
|
end
|
19
15
|
|
20
16
|
def relation_for(object)
|
@@ -25,19 +21,39 @@ module Ransack
|
|
25
21
|
return nil unless attr && attr.valid?
|
26
22
|
name = attr.arel_attribute.name.to_s
|
27
23
|
table = attr.arel_attribute.relation.table_name
|
28
|
-
schema_cache =
|
29
|
-
unless schema_cache.send(
|
24
|
+
schema_cache = self.klass.connection.schema_cache
|
25
|
+
unless schema_cache.send(:data_source_exists?, table)
|
30
26
|
raise "No table named #{table} exists."
|
31
27
|
end
|
32
|
-
|
28
|
+
attr.klass.columns.find { |column| column.name == name }.type
|
33
29
|
end
|
34
30
|
|
35
31
|
def evaluate(search, opts = {})
|
36
32
|
viz = Visitor.new
|
37
33
|
relation = @object.where(viz.accept(search.base))
|
34
|
+
|
38
35
|
if search.sorts.any?
|
39
|
-
relation = relation.except(:order)
|
36
|
+
relation = relation.except(:order)
|
37
|
+
# Rather than applying all of the search's sorts in one fell swoop,
|
38
|
+
# as the original implementation does, we apply one at a time.
|
39
|
+
#
|
40
|
+
# If the sort (returned by the Visitor above) is a symbol, we know
|
41
|
+
# that it represents a scope on the model and we can apply that
|
42
|
+
# scope.
|
43
|
+
#
|
44
|
+
# Otherwise, we fall back to the applying the sort with the "order"
|
45
|
+
# method as the original implementation did. Actually the original
|
46
|
+
# implementation used "reorder," which was overkill since we already
|
47
|
+
# have a clean slate after "relation.except(:order)" above.
|
48
|
+
viz.accept(search.sorts).each do |scope_or_sort|
|
49
|
+
if scope_or_sort.is_a?(Symbol)
|
50
|
+
relation = relation.send(scope_or_sort)
|
51
|
+
else
|
52
|
+
relation = relation.order(scope_or_sort)
|
53
|
+
end
|
54
|
+
end
|
40
55
|
end
|
56
|
+
|
41
57
|
opts[:distinct] ? relation.distinct : relation
|
42
58
|
end
|
43
59
|
|
@@ -45,7 +61,7 @@ module Ransack
|
|
45
61
|
exists = false
|
46
62
|
if ransackable_attribute?(str, klass)
|
47
63
|
exists = true
|
48
|
-
elsif (segments = str.split(
|
64
|
+
elsif (segments = str.split(Constants::UNDERSCORE)).size > 1
|
49
65
|
remainder = []
|
50
66
|
found_assoc = nil
|
51
67
|
while !found_assoc && remainder.unshift(segments.pop) &&
|
@@ -80,84 +96,56 @@ module Ransack
|
|
80
96
|
end
|
81
97
|
end
|
82
98
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
#
|
97
|
-
def join_sources
|
98
|
-
base, joins =
|
99
|
-
if ::ActiveRecord::VERSION::MAJOR >= 5
|
100
|
-
[
|
101
|
-
Arel::SelectManager.new(@object.table),
|
102
|
-
@join_dependency.join_constraints(@object.joins_values, @join_type)
|
103
|
-
]
|
99
|
+
# All dependent Arel::Join nodes used in the search query.
|
100
|
+
#
|
101
|
+
# This could otherwise be done as `@object.arel.join_sources`, except
|
102
|
+
# that ActiveRecord's build_joins sets up its own JoinDependency.
|
103
|
+
# This extracts what we need to access the joins using our existing
|
104
|
+
# JoinDependency to track table aliases.
|
105
|
+
#
|
106
|
+
def join_sources
|
107
|
+
base, joins =
|
108
|
+
if ::ActiveRecord::VERSION::STRING > Constants::RAILS_5_2_0
|
109
|
+
alias_tracker = ::ActiveRecord::Associations::AliasTracker.create(self.klass.connection, @object.table.name, [])
|
110
|
+
constraints = if ::Gem::Version.new(::ActiveRecord::VERSION::STRING) >= ::Gem::Version.new(Constants::RAILS_6_0)
|
111
|
+
@join_dependency.join_constraints(@object.joins_values, alias_tracker)
|
104
112
|
else
|
105
|
-
|
106
|
-
Arel::SelectManager.new(@object.engine, @object.table),
|
107
|
-
@join_dependency.join_constraints(@object.joins_values)
|
108
|
-
]
|
109
|
-
end
|
110
|
-
joins.each do |aliased_join|
|
111
|
-
base.from(aliased_join)
|
113
|
+
@join_dependency.join_constraints(@object.joins_values, @join_type, alias_tracker)
|
112
114
|
end
|
113
|
-
base.join_sources
|
114
|
-
end
|
115
|
-
|
116
|
-
else
|
117
115
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
116
|
+
[
|
117
|
+
Arel::SelectManager.new(@object.table),
|
118
|
+
constraints
|
119
|
+
]
|
120
|
+
else
|
121
|
+
[
|
122
|
+
Arel::SelectManager.new(@object.table),
|
123
|
+
@join_dependency.join_constraints(@object.joins_values, @join_type)
|
124
|
+
]
|
124
125
|
end
|
125
|
-
|
126
|
-
|
127
|
-
base
|
128
|
-
joins = @object.joins_values
|
129
|
-
joins.each do |assoc|
|
130
|
-
assoc.join_to(base)
|
131
|
-
end
|
132
|
-
base.join_sources
|
126
|
+
joins = joins.collect(&:joins).flatten if ::ActiveRecord::VERSION::STRING < Constants::RAILS_5_2
|
127
|
+
joins.each do |aliased_join|
|
128
|
+
base.from(aliased_join)
|
133
129
|
end
|
134
|
-
|
130
|
+
base.join_sources
|
135
131
|
end
|
136
132
|
|
137
133
|
def alias_tracker
|
138
|
-
@join_dependency.alias_tracker
|
134
|
+
@join_dependency.send(:alias_tracker)
|
139
135
|
end
|
140
136
|
|
141
137
|
def lock_association(association)
|
142
138
|
@lock_associations << association
|
143
139
|
end
|
144
140
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
}
|
154
|
-
end
|
155
|
-
else
|
156
|
-
def remove_association(association)
|
157
|
-
return if @lock_associations.include?(association)
|
158
|
-
@join_dependency.join_parts.delete(association)
|
159
|
-
@object.joins_values.delete(association)
|
160
|
-
end
|
141
|
+
def remove_association(association)
|
142
|
+
return if @lock_associations.include?(association)
|
143
|
+
@join_dependency.instance_variable_get(:@join_root).children.delete_if { |stashed|
|
144
|
+
stashed.eql?(association)
|
145
|
+
}
|
146
|
+
@object.joins_values.delete_if { |jd|
|
147
|
+
jd.instance_variable_get(:@join_root).children.map(&:object_id) == [association.object_id]
|
148
|
+
}
|
161
149
|
end
|
162
150
|
|
163
151
|
# Build an Arel subquery that selects keys for the top query,
|
@@ -181,8 +169,7 @@ module Ransack
|
|
181
169
|
def build_correlated_subquery(association)
|
182
170
|
join_constraints = extract_joins(association)
|
183
171
|
join_root = join_constraints.shift
|
184
|
-
|
185
|
-
correlated_key = join_root.right.expr.left
|
172
|
+
correlated_key = extract_correlated_key(join_root)
|
186
173
|
subquery = Arel::SelectManager.new(association.base_klass)
|
187
174
|
subquery.from(join_root.left)
|
188
175
|
subquery.project(correlated_key)
|
@@ -198,11 +185,17 @@ module Ransack
|
|
198
185
|
|
199
186
|
private
|
200
187
|
|
201
|
-
def
|
202
|
-
|
203
|
-
|
188
|
+
def extract_correlated_key(join_root)
|
189
|
+
correlated_key = join_root.right.expr.left
|
190
|
+
|
191
|
+
if correlated_key.is_a? Arel::Nodes::And
|
192
|
+
correlated_key = correlated_key.left.left
|
193
|
+
elsif correlated_key.is_a? Arel::Nodes::Equality
|
194
|
+
correlated_key = correlated_key.left
|
195
|
+
elsif correlated_key.is_a? Arel::Nodes::Grouping
|
196
|
+
correlated_key = join_root.right.expr.right.left
|
204
197
|
else
|
205
|
-
|
198
|
+
correlated_key
|
206
199
|
end
|
207
200
|
end
|
208
201
|
|
@@ -250,7 +243,9 @@ module Ransack
|
|
250
243
|
# Checkout active_record/relation/query_methods.rb +build_joins+ for
|
251
244
|
# reference. Lots of duplicated code maybe we can avoid it
|
252
245
|
def build_joins(relation)
|
253
|
-
buckets = relation.joins_values
|
246
|
+
buckets = relation.joins_values + relation.left_outer_joins_values
|
247
|
+
|
248
|
+
buckets = buckets.group_by do |join|
|
254
249
|
case join
|
255
250
|
when String
|
256
251
|
:string_join
|
@@ -268,123 +263,138 @@ module Ransack
|
|
268
263
|
association_joins = buckets[:association_join]
|
269
264
|
stashed_association_joins = buckets[:stashed_join]
|
270
265
|
join_nodes = buckets[:join_node].uniq
|
271
|
-
string_joins = buckets[:string_join].map(&:strip)
|
266
|
+
string_joins = buckets[:string_join].map(&:strip)
|
267
|
+
string_joins.uniq!
|
272
268
|
|
273
|
-
join_list =
|
274
|
-
if ::ActiveRecord::VERSION::MAJOR >= 5
|
275
|
-
join_nodes +
|
276
|
-
convert_join_strings_to_ast(relation.table, string_joins)
|
277
|
-
else
|
278
|
-
relation.send :custom_join_ast,
|
279
|
-
relation.table.from(relation.table), string_joins
|
280
|
-
end
|
281
|
-
|
282
|
-
join_dependency = JoinDependency.new(
|
283
|
-
relation.klass, association_joins, join_list
|
284
|
-
)
|
285
|
-
|
286
|
-
join_nodes.each do |join|
|
287
|
-
join_dependency.alias_tracker.aliases[join.left.name.downcase] = 1
|
288
|
-
end
|
269
|
+
join_list = join_nodes + convert_join_strings_to_ast(relation.table, string_joins)
|
289
270
|
|
290
|
-
if ::ActiveRecord::VERSION::STRING
|
291
|
-
join_dependency
|
271
|
+
if ::ActiveRecord::VERSION::STRING < Constants::RAILS_5_2_0
|
272
|
+
join_dependency = Polyamorous::JoinDependency.new(relation.klass, association_joins, join_list)
|
273
|
+
join_nodes.each do |join|
|
274
|
+
join_dependency.send(:alias_tracker).aliases[join.left.name.downcase] = 1
|
275
|
+
end
|
276
|
+
elsif ::ActiveRecord::VERSION::STRING == Constants::RAILS_5_2_0
|
277
|
+
alias_tracker = ::ActiveRecord::Associations::AliasTracker.create(self.klass.connection, relation.table.name, join_list)
|
278
|
+
join_dependency = Polyamorous::JoinDependency.new(relation.klass, relation.table, association_joins, alias_tracker)
|
279
|
+
join_nodes.each do |join|
|
280
|
+
join_dependency.send(:alias_tracker).aliases[join.left.name.downcase] = 1
|
281
|
+
end
|
292
282
|
else
|
293
|
-
|
283
|
+
alias_tracker = ::ActiveRecord::Associations::AliasTracker.create(self.klass.connection, relation.table.name, join_list)
|
284
|
+
join_dependency = if ::Gem::Version.new(::ActiveRecord::VERSION::STRING) >= ::Gem::Version.new(Constants::RAILS_6_0)
|
285
|
+
Polyamorous::JoinDependency.new(relation.klass, relation.table, association_joins, Arel::Nodes::OuterJoin)
|
286
|
+
else
|
287
|
+
Polyamorous::JoinDependency.new(relation.klass, relation.table, association_joins)
|
288
|
+
end
|
289
|
+
join_dependency.instance_variable_set(:@alias_tracker, alias_tracker)
|
290
|
+
join_nodes.each do |join|
|
291
|
+
join_dependency.send(:alias_tracker).aliases[join.left.name.downcase] = 1
|
292
|
+
end
|
294
293
|
end
|
294
|
+
join_dependency
|
295
295
|
end
|
296
296
|
|
297
297
|
def convert_join_strings_to_ast(table, joins)
|
298
|
+
joins.map! { |join| table.create_string_join(Arel.sql(join)) unless join.blank? }
|
299
|
+
joins.compact!
|
298
300
|
joins
|
299
|
-
.flatten
|
300
|
-
.reject(&:blank?)
|
301
|
-
.map { |join| table.create_string_join(Arel.sql(join)) }
|
302
301
|
end
|
303
302
|
|
304
303
|
def build_or_find_association(name, parent = @base, klass = nil)
|
305
304
|
find_association(name, parent, klass) or build_association(name, parent, klass)
|
306
305
|
end
|
307
306
|
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
@
|
312
|
-
|
313
|
-
(@associations_pot.empty? || @associations_pot[assoc] == parent) &&
|
314
|
-
(!klass || assoc.reflection.klass == klass)
|
315
|
-
end
|
307
|
+
def find_association(name, parent = @base, klass = nil)
|
308
|
+
@join_dependency.instance_variable_get(:@join_root).children.detect do |assoc|
|
309
|
+
assoc.reflection.name == name && assoc.table &&
|
310
|
+
(@associations_pot.empty? || @associations_pot[assoc] == parent || !@associations_pot.key?(assoc)) &&
|
311
|
+
(!klass || assoc.reflection.klass == klass)
|
316
312
|
end
|
313
|
+
end
|
317
314
|
|
318
|
-
|
319
|
-
|
315
|
+
def build_association(name, parent = @base, klass = nil)
|
316
|
+
if ::Gem::Version.new(::ActiveRecord::VERSION::STRING) >= ::Gem::Version.new(Constants::RAILS_6_0)
|
317
|
+
jd = Polyamorous::JoinDependency.new(
|
318
|
+
parent.base_klass,
|
319
|
+
parent.table,
|
320
|
+
Polyamorous::Join.new(name, @join_type, klass),
|
321
|
+
@join_type
|
322
|
+
)
|
323
|
+
found_association = jd.instance_variable_get(:@join_root).children.last
|
324
|
+
elsif ::Gem::Version.new(::ActiveRecord::VERSION::STRING) < ::Gem::Version.new(Constants::RAILS_5_2_0)
|
325
|
+
jd = Polyamorous::JoinDependency.new(
|
320
326
|
parent.base_klass,
|
321
327
|
Polyamorous::Join.new(name, @join_type, klass),
|
322
328
|
[]
|
323
329
|
)
|
324
330
|
found_association = jd.join_root.children.last
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
@join_dependency.join_root.children.push found_association
|
330
|
-
|
331
|
-
# Builds the arel nodes properly for this association
|
332
|
-
@join_dependency.send(
|
333
|
-
:construct_tables!, jd.join_root, found_association
|
334
|
-
)
|
335
|
-
|
336
|
-
# Leverage the stashed association functionality in AR
|
337
|
-
@object = @object.joins(jd)
|
338
|
-
|
339
|
-
found_association
|
340
|
-
end
|
341
|
-
|
342
|
-
def extract_joins(association)
|
343
|
-
parent = @join_dependency.join_root
|
344
|
-
reflection = association.reflection
|
345
|
-
join_constraints = association.join_constraints(
|
331
|
+
elsif ::ActiveRecord::VERSION::STRING == Constants::RAILS_5_2_0
|
332
|
+
alias_tracker = ::ActiveRecord::Associations::AliasTracker.create(self.klass.connection, parent.table.name, [])
|
333
|
+
jd = Polyamorous::JoinDependency.new(
|
334
|
+
parent.base_klass,
|
346
335
|
parent.table,
|
336
|
+
Polyamorous::Join.new(name, @join_type, klass),
|
337
|
+
alias_tracker
|
338
|
+
)
|
339
|
+
found_association = jd.instance_variable_get(:@join_root).children.last
|
340
|
+
else
|
341
|
+
jd = Polyamorous::JoinDependency.new(
|
347
342
|
parent.base_klass,
|
348
|
-
|
349
|
-
|
350
|
-
association.tables,
|
351
|
-
reflection.scope_chain,
|
352
|
-
reflection.chain
|
343
|
+
parent.table,
|
344
|
+
Polyamorous::Join.new(name, @join_type, klass)
|
353
345
|
)
|
354
|
-
|
346
|
+
found_association = jd.instance_variable_get(:@join_root).children.last
|
355
347
|
end
|
356
348
|
|
357
|
-
|
349
|
+
@associations_pot[found_association] = parent
|
358
350
|
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
Polyamorous::Join.new(name, @join_type, klass),
|
363
|
-
parent
|
364
|
-
)
|
365
|
-
found_association = @join_dependency.join_associations.last
|
366
|
-
# Leverage the stashed association functionality in AR
|
367
|
-
@object = @object.joins(found_association)
|
351
|
+
# TODO maybe we dont need to push associations here, we could loop
|
352
|
+
# through the @associations_pot instead
|
353
|
+
@join_dependency.instance_variable_get(:@join_root).children.push found_association
|
368
354
|
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
association.join_to(query).join_sources
|
375
|
-
end
|
376
|
-
|
377
|
-
def find_association(name, parent = @base, klass = nil)
|
378
|
-
found_association = @join_dependency.join_associations
|
379
|
-
.detect do |assoc|
|
380
|
-
assoc.reflection.name == name &&
|
381
|
-
assoc.parent == parent &&
|
382
|
-
(!klass || assoc.reflection.klass == klass)
|
383
|
-
end
|
355
|
+
# Builds the arel nodes properly for this association
|
356
|
+
if ::ActiveRecord::VERSION::STRING > Constants::RAILS_5_2_0
|
357
|
+
@join_dependency.send(:construct_tables!, jd.instance_variable_get(:@join_root))
|
358
|
+
else
|
359
|
+
@join_dependency.send(:construct_tables!, jd.instance_variable_get(:@join_root), found_association)
|
384
360
|
end
|
385
361
|
|
362
|
+
# Leverage the stashed association functionality in AR
|
363
|
+
@object = @object.joins(jd)
|
364
|
+
found_association
|
386
365
|
end
|
387
366
|
|
367
|
+
def extract_joins(association)
|
368
|
+
parent = @join_dependency.instance_variable_get(:@join_root)
|
369
|
+
reflection = association.reflection
|
370
|
+
join_constraints = if ::ActiveRecord::VERSION::STRING < Constants::RAILS_5_1
|
371
|
+
association.join_constraints(
|
372
|
+
parent.table,
|
373
|
+
parent.base_klass,
|
374
|
+
association,
|
375
|
+
Arel::Nodes::OuterJoin,
|
376
|
+
association.tables,
|
377
|
+
reflection.scope_chain,
|
378
|
+
reflection.chain
|
379
|
+
)
|
380
|
+
elsif ::ActiveRecord::VERSION::STRING <= Constants::RAILS_5_2_0
|
381
|
+
association.join_constraints(
|
382
|
+
parent.table,
|
383
|
+
parent.base_klass,
|
384
|
+
Arel::Nodes::OuterJoin,
|
385
|
+
association.tables,
|
386
|
+
reflection.chain
|
387
|
+
)
|
388
|
+
else
|
389
|
+
association.join_constraints(
|
390
|
+
parent.table,
|
391
|
+
parent.base_klass,
|
392
|
+
Arel::Nodes::OuterJoin,
|
393
|
+
@join_dependency.instance_variable_get(:@alias_tracker)
|
394
|
+
)
|
395
|
+
end
|
396
|
+
join_constraints.to_a.flatten
|
397
|
+
end
|
388
398
|
end
|
389
399
|
end
|
390
400
|
end
|
@@ -102,9 +102,12 @@ module Ransack
|
|
102
102
|
# replace % \ to \% \\
|
103
103
|
def escape_wildcards(unescaped)
|
104
104
|
case ActiveRecord::Base.connection.adapter_name
|
105
|
-
when "Mysql2".freeze
|
106
|
-
# Necessary for
|
107
|
-
unescaped.to_s.gsub(/([
|
105
|
+
when "Mysql2".freeze
|
106
|
+
# Necessary for MySQL
|
107
|
+
unescaped.to_s.gsub(/([\\%_])/, '\\\\\\1')
|
108
|
+
when "PostgreSQL".freeze
|
109
|
+
# Necessary for PostgreSQL
|
110
|
+
unescaped.to_s.gsub(/([\\%_.])/, '\\\\\\1')
|
108
111
|
else
|
109
112
|
unescaped
|
110
113
|
end
|
@@ -30,22 +30,20 @@ module Ransack
|
|
30
30
|
@associations_pot = {}
|
31
31
|
@lock_associations = []
|
32
32
|
|
33
|
-
if ::ActiveRecord::VERSION::STRING >= Constants::
|
33
|
+
if ::ActiveRecord::VERSION::STRING >= Constants::RAILS_5_2
|
34
|
+
@base = @join_dependency.instance_variable_get(:@join_root)
|
35
|
+
else
|
34
36
|
@base = @join_dependency.join_root
|
35
37
|
@engine = @base.base_klass.arel_engine
|
36
|
-
else
|
37
|
-
@base = @join_dependency.join_base
|
38
|
-
@engine = @base.arel_engine
|
39
38
|
end
|
39
|
+
end
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
@bind_pairs
|
45
|
-
parent, attr_name = get_parent_and_attribute_name(key)
|
46
|
-
if parent && attr_name
|
47
|
-
hash[key] = [parent, attr_name]
|
48
|
-
end
|
41
|
+
def bind_pair_for(key)
|
42
|
+
@bind_pairs ||= {}
|
43
|
+
|
44
|
+
@bind_pairs[key] ||= begin
|
45
|
+
parent, attr_name = get_parent_and_attribute_name(key.to_s)
|
46
|
+
[parent, attr_name] if parent && attr_name
|
49
47
|
end
|
50
48
|
end
|
51
49
|
|
@@ -54,10 +52,6 @@ module Ransack
|
|
54
52
|
obj
|
55
53
|
elsif obj.respond_to? :klass
|
56
54
|
obj.klass
|
57
|
-
elsif obj.respond_to? :active_record # Rails 3
|
58
|
-
obj.active_record
|
59
|
-
elsif obj.respond_to? :base_klass # Rails 4
|
60
|
-
obj.base_klass
|
61
55
|
else
|
62
56
|
raise ArgumentError, "Don't know how to klassify #{obj.inspect}"
|
63
57
|
end
|
@@ -33,8 +33,8 @@ module Ransack
|
|
33
33
|
predicate = attribute.attr.public_send(arel_pred, arel_values)
|
34
34
|
|
35
35
|
if in_predicate?(predicate)
|
36
|
-
predicate.right = predicate.right.map do |
|
37
|
-
casted_array?(
|
36
|
+
predicate.right = predicate.right.map do |pr|
|
37
|
+
casted_array?(pr) ? format_values_for(pr) : pr
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
@@ -43,7 +43,7 @@ module Ransack
|
|
43
43
|
|
44
44
|
def in_predicate?(predicate)
|
45
45
|
return unless defined?(Arel::Nodes::Casted)
|
46
|
-
predicate.class == Arel::Nodes::In
|
46
|
+
predicate.class == Arel::Nodes::In || predicate.class == Arel::Nodes::NotIn
|
47
47
|
end
|
48
48
|
|
49
49
|
def casted_array?(predicate)
|
@@ -2,11 +2,7 @@ module Ransack
|
|
2
2
|
module Translate
|
3
3
|
|
4
4
|
def self.i18n_key(klass)
|
5
|
-
|
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
|
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
|
@@ -12,12 +12,3 @@ ActiveSupport.on_load(:active_record) do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
require 'ransack/adapters/active_record/context'
|
15
|
-
|
16
|
-
case ActiveRecord::VERSION::STRING
|
17
|
-
when /^3\.0\./
|
18
|
-
require 'ransack/adapters/active_record/3.0/context'
|
19
|
-
when /^3\.1\./
|
20
|
-
require 'ransack/adapters/active_record/3.1/context'
|
21
|
-
when /^3\.2\./
|
22
|
-
require 'ransack/adapters/active_record/3.2/context'
|
23
|
-
end
|