ransack 2.4.2 → 4.0.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.
- checksums.yaml +4 -4
- data/.github/workflows/codeql.yml +72 -0
- data/.github/workflows/cronjob.yml +6 -9
- data/.github/workflows/deploy.yml +35 -0
- data/.github/workflows/rubocop.yml +1 -1
- data/.github/workflows/test-deploy.yml +29 -0
- data/.github/workflows/test.yml +22 -48
- data/.nojekyll +0 -0
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +208 -11
- data/CONTRIBUTING.md +41 -18
- data/Gemfile +10 -10
- data/README.md +44 -977
- data/bug_report_templates/test-ransacker-arel-present-predicate.rb +4 -0
- data/docs/.gitignore +19 -0
- data/docs/.nojekyll +0 -0
- data/docs/babel.config.js +3 -0
- data/docs/blog/2022-03-27-ransack-3.0.0.md +20 -0
- data/docs/docs/getting-started/_category_.json +4 -0
- data/docs/docs/getting-started/advanced-mode.md +46 -0
- data/docs/docs/getting-started/configuration.md +47 -0
- data/docs/docs/getting-started/search-matches.md +67 -0
- data/docs/docs/getting-started/simple-mode.md +288 -0
- data/docs/docs/getting-started/sorting.md +79 -0
- data/docs/docs/getting-started/using-predicates.md +282 -0
- data/docs/docs/going-further/_category_.json +4 -0
- data/docs/docs/going-further/acts-as-taggable-on.md +114 -0
- data/docs/docs/going-further/associations.md +70 -0
- data/docs/docs/going-further/custom-predicates.md +52 -0
- data/docs/docs/going-further/documentation.md +43 -0
- data/docs/docs/going-further/exporting-to-csv.md +49 -0
- data/docs/docs/going-further/external-guides.md +57 -0
- data/docs/docs/going-further/form-customisation.md +63 -0
- data/docs/docs/going-further/i18n.md +53 -0
- data/docs/docs/going-further/merging-searches.md +41 -0
- data/docs/docs/going-further/other-notes.md +428 -0
- data/docs/docs/going-further/polymorphic-search.md +40 -0
- data/docs/docs/going-further/ransackers.md +331 -0
- data/docs/docs/going-further/release_process.md +36 -0
- data/docs/docs/going-further/saving-queries.md +82 -0
- data/docs/docs/going-further/searching-postgres.md +57 -0
- data/docs/docs/going-further/wiki-contributors.md +82 -0
- data/docs/docs/intro.md +99 -0
- data/docs/docusaurus.config.js +120 -0
- data/docs/package.json +42 -0
- data/docs/sidebars.js +31 -0
- data/docs/src/components/HomepageFeatures/index.js +64 -0
- data/docs/src/components/HomepageFeatures/styles.module.css +11 -0
- data/docs/src/css/custom.css +39 -0
- data/docs/src/pages/index.module.css +23 -0
- data/docs/src/pages/markdown-page.md +7 -0
- data/docs/static/.nojekyll +0 -0
- data/docs/static/img/docusaurus.png +0 -0
- data/docs/static/img/favicon.ico +0 -0
- data/docs/static/img/logo.svg +1 -0
- data/docs/static/img/tutorial/docsVersionDropdown.png +0 -0
- data/docs/static/img/tutorial/localeDropdown.png +0 -0
- data/docs/static/img/undraw_docusaurus_mountain.svg +171 -0
- data/docs/static/img/undraw_docusaurus_react.svg +170 -0
- data/docs/static/img/undraw_docusaurus_tree.svg +40 -0
- data/docs/yarn.lock +8790 -0
- data/lib/polyamorous/activerecord_6.1_ruby_2/join_association.rb +0 -4
- data/lib/polyamorous/activerecord_6.1_ruby_2/join_dependency.rb +0 -1
- data/lib/polyamorous/activerecord_6.1_ruby_2/reflection.rb +11 -1
- data/lib/polyamorous/activerecord_7.1_ruby_2/join_association.rb +1 -0
- data/lib/polyamorous/activerecord_7.1_ruby_2/join_dependency.rb +1 -0
- data/lib/polyamorous/activerecord_7.1_ruby_2/reflection.rb +1 -0
- data/lib/ransack/adapters/active_record/base.rb +79 -10
- data/lib/ransack/adapters/active_record/context.rb +24 -51
- data/lib/ransack/configuration.rb +39 -12
- data/lib/ransack/constants.rb +125 -3
- data/lib/ransack/context.rb +34 -5
- data/lib/ransack/helpers/form_builder.rb +3 -3
- data/lib/ransack/helpers/form_helper.rb +14 -5
- data/lib/ransack/locale/sv.yml +70 -0
- data/lib/ransack/nodes/attribute.rb +2 -2
- data/lib/ransack/nodes/condition.rb +80 -7
- data/lib/ransack/nodes/grouping.rb +3 -3
- data/lib/ransack/nodes/node.rb +1 -1
- data/lib/ransack/nodes/sort.rb +2 -2
- data/lib/ransack/nodes/value.rb +2 -2
- data/lib/ransack/predicate.rb +1 -1
- data/lib/ransack/ransacker.rb +1 -1
- data/lib/ransack/search.rb +13 -7
- data/lib/ransack/translate.rb +3 -3
- data/lib/ransack/version.rb +1 -1
- data/lib/ransack/visitor.rb +38 -2
- data/lib/ransack.rb +3 -6
- data/ransack.gemspec +5 -5
- data/spec/helpers/polyamorous_helper.rb +2 -8
- data/spec/polyamorous/activerecord_compatibility_spec.rb +15 -0
- data/spec/polyamorous/join_association_spec.rb +1 -6
- data/spec/polyamorous/join_dependency_spec.rb +0 -16
- data/spec/ransack/adapters/active_record/base_spec.rb +101 -11
- data/spec/ransack/configuration_spec.rb +23 -9
- data/spec/ransack/helpers/form_builder_spec.rb +8 -8
- data/spec/ransack/helpers/form_helper_spec.rb +93 -4
- data/spec/ransack/nodes/condition_spec.rb +37 -0
- data/spec/ransack/nodes/value_spec.rb +115 -0
- data/spec/ransack/predicate_spec.rb +36 -1
- data/spec/ransack/search_spec.rb +140 -27
- data/spec/ransack/translate_spec.rb +1 -1
- data/spec/support/schema.rb +75 -9
- metadata +83 -37
- data/docs/release_process.md +0 -20
- data/lib/polyamorous/activerecord_5.2_ruby_2/join_association.rb +0 -24
- data/lib/polyamorous/activerecord_5.2_ruby_2/join_dependency.rb +0 -79
- data/lib/polyamorous/activerecord_5.2_ruby_2/reflection.rb +0 -11
- data/lib/polyamorous/activerecord_6.0_ruby_2/join_association.rb +0 -1
- data/lib/polyamorous/activerecord_6.0_ruby_2/join_dependency.rb +0 -80
- data/lib/polyamorous/activerecord_6.0_ruby_2/reflection.rb +0 -1
- data/lib/ransack/adapters/active_record/ransack/constants.rb +0 -128
- data/lib/ransack/adapters/active_record/ransack/context.rb +0 -56
- data/lib/ransack/adapters/active_record/ransack/nodes/condition.rb +0 -68
- data/lib/ransack/adapters/active_record/ransack/translate.rb +0 -8
- data/lib/ransack/adapters/active_record/ransack/visitor.rb +0 -47
- data/lib/ransack/adapters.rb +0 -64
- data/lib/ransack/nodes.rb +0 -8
- /data/docs/{img → docs/going-further/img}/create_release.png +0 -0
- /data/{logo → docs/static/logo}/ransack-h.png +0 -0
- /data/{logo → docs/static/logo}/ransack-h.svg +0 -0
- /data/{logo → docs/static/logo}/ransack-v.png +0 -0
- /data/{logo → docs/static/logo}/ransack-v.svg +0 -0
- /data/{logo → docs/static/logo}/ransack.png +0 -0
- /data/{logo → docs/static/logo}/ransack.svg +0 -0
- /data/lib/polyamorous/{activerecord_6.2_ruby_2 → activerecord_7.0_ruby_2}/join_association.rb +0 -0
- /data/lib/polyamorous/{activerecord_6.2_ruby_2 → activerecord_7.0_ruby_2}/join_dependency.rb +0 -0
- /data/lib/polyamorous/{activerecord_6.2_ruby_2 → activerecord_7.0_ruby_2}/reflection.rb +0 -0
- /data/lib/ransack/{adapters/active_record.rb → active_record.rb} +0 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
sv:
|
|
2
|
+
ransack:
|
|
3
|
+
search: "sök"
|
|
4
|
+
predicate: "predikat"
|
|
5
|
+
and: "och"
|
|
6
|
+
or: "eller"
|
|
7
|
+
any: "vilken som"
|
|
8
|
+
all: "alla"
|
|
9
|
+
combinator: "kombinator"
|
|
10
|
+
attribute: "attribut"
|
|
11
|
+
value: "värde"
|
|
12
|
+
condition: "villkor"
|
|
13
|
+
sort: "sortera"
|
|
14
|
+
asc: "stigande"
|
|
15
|
+
desc: "fallande"
|
|
16
|
+
predicates:
|
|
17
|
+
eq: "lika med"
|
|
18
|
+
eq_any: "lika med vilket som"
|
|
19
|
+
eq_all: "lika med alla"
|
|
20
|
+
not_eq: "inte lika med"
|
|
21
|
+
not_eq_any: "inte lika med någon"
|
|
22
|
+
not_eq_all: "inte lika med alla"
|
|
23
|
+
matches: "matchar"
|
|
24
|
+
matches_any: "matchar någon"
|
|
25
|
+
matches_all: "matchar alla"
|
|
26
|
+
does_not_match: "matchar inte"
|
|
27
|
+
does_not_match_any: "matchar inte någon"
|
|
28
|
+
does_not_match_all: "matchar inte alla"
|
|
29
|
+
lt: "mindre än"
|
|
30
|
+
lt_any: "mindre än någon"
|
|
31
|
+
lt_all: "mindre än alla"
|
|
32
|
+
lteq: "mindre än eller lika med"
|
|
33
|
+
lteq_any: "mindre än eller lika med någon"
|
|
34
|
+
lteq_all: "mindre än eller lika med alla"
|
|
35
|
+
gt: "större än"
|
|
36
|
+
gt_any: "större än någon"
|
|
37
|
+
gt_all: "större än alla"
|
|
38
|
+
gteq: "större än eller lika med"
|
|
39
|
+
gteq_any: "större än eller lika med någon"
|
|
40
|
+
gteq_all: "större än eller lika med alla"
|
|
41
|
+
in: "i"
|
|
42
|
+
in_any: "i någon"
|
|
43
|
+
in_all: "i alla"
|
|
44
|
+
not_in: "inte i"
|
|
45
|
+
not_in_any: "inte i någon"
|
|
46
|
+
not_in_all: "inte i alla"
|
|
47
|
+
cont: "innehåller"
|
|
48
|
+
cont_any: "innehåller någon"
|
|
49
|
+
cont_all: "innehåller alla"
|
|
50
|
+
not_cont: "innehåller inte"
|
|
51
|
+
not_cont_any: "innehåller inte någon"
|
|
52
|
+
not_cont_all: "innehåller inte alla"
|
|
53
|
+
start: "börjar med"
|
|
54
|
+
start_any: "börjar med någon"
|
|
55
|
+
start_all: "börjar med alla"
|
|
56
|
+
not_start: "börjar inte med"
|
|
57
|
+
not_start_any: "börjar inte med någon"
|
|
58
|
+
not_start_all: "börjar inte med alla"
|
|
59
|
+
end: "slutar med"
|
|
60
|
+
end_any: "slutar med någon"
|
|
61
|
+
end_all: "slutar med alla"
|
|
62
|
+
not_end: "slutar inte med"
|
|
63
|
+
not_end_any: "slutar inte med någon"
|
|
64
|
+
not_end_all: "slutar inte med alla"
|
|
65
|
+
'true': "är sant"
|
|
66
|
+
'false': "är falskt"
|
|
67
|
+
present: "existerar"
|
|
68
|
+
blank: "är tom"
|
|
69
|
+
'null': "är null"
|
|
70
|
+
not_null: "är inte null"
|
|
@@ -5,8 +5,8 @@ module Ransack
|
|
|
5
5
|
|
|
6
6
|
attr_reader :name, :ransacker_args
|
|
7
7
|
|
|
8
|
-
delegate :blank?, :present?, :
|
|
9
|
-
delegate :engine, :
|
|
8
|
+
delegate :blank?, :present?, to: :name
|
|
9
|
+
delegate :engine, to: :context
|
|
10
10
|
|
|
11
11
|
def initialize(context, name = nil, ransacker_args = [])
|
|
12
12
|
super(context)
|
|
@@ -2,8 +2,8 @@ module Ransack
|
|
|
2
2
|
module Nodes
|
|
3
3
|
class Condition < Node
|
|
4
4
|
i18n_word :attribute, :predicate, :combinator, :value
|
|
5
|
-
i18n_alias :
|
|
6
|
-
:
|
|
5
|
+
i18n_alias a: :attribute, p: :predicate,
|
|
6
|
+
m: :combinator, v: :value
|
|
7
7
|
|
|
8
8
|
attr_accessor :predicate
|
|
9
9
|
|
|
@@ -15,10 +15,10 @@ module Ransack
|
|
|
15
15
|
if attributes.size > 0 && predicate
|
|
16
16
|
condition = self.new(context)
|
|
17
17
|
condition.build(
|
|
18
|
-
:
|
|
19
|
-
:
|
|
20
|
-
:
|
|
21
|
-
:
|
|
18
|
+
a: attributes,
|
|
19
|
+
p: predicate.name,
|
|
20
|
+
m: combinator,
|
|
21
|
+
v: predicate.wants_array ? Array(values) : [values]
|
|
22
22
|
)
|
|
23
23
|
# TODO: Figure out what to do with multiple types of attributes,
|
|
24
24
|
# if anything. Tempted to go with "garbage in, garbage out" here.
|
|
@@ -283,12 +283,85 @@ module Ransack
|
|
|
283
283
|
predicate.negative?
|
|
284
284
|
end
|
|
285
285
|
|
|
286
|
+
def arel_predicate
|
|
287
|
+
predicate = attributes.map { |attribute|
|
|
288
|
+
association = attribute.parent
|
|
289
|
+
if negative? && attribute.associated_collection?
|
|
290
|
+
query = context.build_correlated_subquery(association)
|
|
291
|
+
context.remove_association(association)
|
|
292
|
+
if self.predicate_name == 'not_null' && self.value
|
|
293
|
+
query.where(format_predicate(attribute))
|
|
294
|
+
Arel::Nodes::In.new(context.primary_key, Arel.sql(query.to_sql))
|
|
295
|
+
else
|
|
296
|
+
query.where(format_predicate(attribute).not)
|
|
297
|
+
Arel::Nodes::NotIn.new(context.primary_key, Arel.sql(query.to_sql))
|
|
298
|
+
end
|
|
299
|
+
else
|
|
300
|
+
format_predicate(attribute)
|
|
301
|
+
end
|
|
302
|
+
}.reduce(combinator_method)
|
|
303
|
+
|
|
304
|
+
if replace_right_node?(predicate)
|
|
305
|
+
# Replace right node object to plain integer value in order to avoid
|
|
306
|
+
# ActiveModel::RangeError from Arel::Node::Casted.
|
|
307
|
+
# The error can be ignored here because RDBMSs accept large numbers
|
|
308
|
+
# in condition clauses.
|
|
309
|
+
plain_value = predicate.right.value
|
|
310
|
+
predicate.right = plain_value
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
predicate
|
|
314
|
+
end
|
|
315
|
+
|
|
286
316
|
private
|
|
287
317
|
|
|
318
|
+
def combinator_method
|
|
319
|
+
combinator === Constants::OR ? :or : :and
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
def format_predicate(attribute)
|
|
323
|
+
arel_pred = arel_predicate_for_attribute(attribute)
|
|
324
|
+
arel_values = formatted_values_for_attribute(attribute)
|
|
325
|
+
predicate = attr_value_for_attribute(attribute).public_send(arel_pred, arel_values)
|
|
326
|
+
|
|
327
|
+
if in_predicate?(predicate)
|
|
328
|
+
predicate.right = predicate.right.map do |pr|
|
|
329
|
+
casted_array?(pr) ? format_values_for(pr) : pr
|
|
330
|
+
end
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
predicate
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
def in_predicate?(predicate)
|
|
337
|
+
return unless defined?(Arel::Nodes::Casted)
|
|
338
|
+
predicate.class == Arel::Nodes::In || predicate.class == Arel::Nodes::NotIn
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
def casted_array?(predicate)
|
|
342
|
+
predicate.value.is_a?(Array) && predicate.is_a?(Arel::Nodes::Casted)
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
def format_values_for(predicate)
|
|
346
|
+
predicate.value.map do |val|
|
|
347
|
+
val.is_a?(String) ? Arel::Nodes.build_quoted(val) : val
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
def replace_right_node?(predicate)
|
|
352
|
+
return false unless predicate.is_a?(Arel::Nodes::Binary)
|
|
353
|
+
|
|
354
|
+
arel_node = predicate.right
|
|
355
|
+
return false unless arel_node.is_a?(Arel::Nodes::Casted)
|
|
356
|
+
|
|
357
|
+
relation, name = arel_node.attribute.values
|
|
358
|
+
attribute_type = relation.type_for_attribute(name).type
|
|
359
|
+
attribute_type == :integer && arel_node.value.is_a?(Integer)
|
|
360
|
+
end
|
|
361
|
+
|
|
288
362
|
def valid_combinator?
|
|
289
363
|
attributes.size < 2 || Constants::AND_OR.include?(combinator)
|
|
290
364
|
end
|
|
291
|
-
|
|
292
365
|
end
|
|
293
366
|
end
|
|
294
367
|
end
|
|
@@ -7,9 +7,9 @@ module Ransack
|
|
|
7
7
|
alias :m= :combinator=
|
|
8
8
|
|
|
9
9
|
i18n_word :condition, :and, :or
|
|
10
|
-
i18n_alias :
|
|
10
|
+
i18n_alias c: :condition, n: :and, o: :or
|
|
11
11
|
|
|
12
|
-
delegate :each, :
|
|
12
|
+
delegate :each, to: :values
|
|
13
13
|
|
|
14
14
|
def initialize(context, combinator = nil)
|
|
15
15
|
super(context)
|
|
@@ -22,7 +22,7 @@ module Ransack
|
|
|
22
22
|
|
|
23
23
|
def translate(key, options = {})
|
|
24
24
|
super or Translate.attribute(
|
|
25
|
-
key.to_s, options.merge(:
|
|
25
|
+
key.to_s, options.merge(context: context)
|
|
26
26
|
)
|
|
27
27
|
end
|
|
28
28
|
|
data/lib/ransack/nodes/node.rb
CHANGED
data/lib/ransack/nodes/sort.rb
CHANGED
data/lib/ransack/nodes/value.rb
CHANGED
|
@@ -2,7 +2,7 @@ module Ransack
|
|
|
2
2
|
module Nodes
|
|
3
3
|
class Value < Node
|
|
4
4
|
attr_accessor :value
|
|
5
|
-
delegate :present?, :blank?, :
|
|
5
|
+
delegate :present?, :blank?, to: :value
|
|
6
6
|
|
|
7
7
|
def initialize(context, value = nil)
|
|
8
8
|
super(context)
|
|
@@ -26,7 +26,7 @@ module Ransack
|
|
|
26
26
|
case type
|
|
27
27
|
when :date
|
|
28
28
|
cast_to_date(value)
|
|
29
|
-
when :datetime, :timestamp, :time
|
|
29
|
+
when :datetime, :timestamp, :time, :timestamptz
|
|
30
30
|
cast_to_time(value)
|
|
31
31
|
when :boolean
|
|
32
32
|
cast_to_boolean(value)
|
data/lib/ransack/predicate.rb
CHANGED
data/lib/ransack/ransacker.rb
CHANGED
data/lib/ransack/search.rb
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
require 'ransack/nodes'
|
|
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'
|
|
2
8
|
require 'ransack/context'
|
|
3
|
-
Ransack::Adapters.object_mapper.require_search
|
|
4
9
|
require 'ransack/naming'
|
|
5
10
|
|
|
6
11
|
module Ransack
|
|
@@ -9,16 +14,17 @@ module Ransack
|
|
|
9
14
|
|
|
10
15
|
attr_reader :base, :context
|
|
11
16
|
|
|
12
|
-
delegate :object, :klass, :
|
|
17
|
+
delegate :object, :klass, to: :context
|
|
13
18
|
delegate :new_grouping, :new_condition,
|
|
14
19
|
:build_grouping, :build_condition,
|
|
15
|
-
:translate, :
|
|
20
|
+
:translate, to: :base
|
|
16
21
|
|
|
17
22
|
def initialize(object, params = {}, options = {})
|
|
23
|
+
strip_whitespace = options.fetch(:strip_whitespace, Ransack.options[:strip_whitespace])
|
|
18
24
|
params = params.to_unsafe_h if params.respond_to?(:to_unsafe_h)
|
|
19
25
|
if params.is_a? Hash
|
|
20
26
|
params = params.dup
|
|
21
|
-
params = params.transform_values { |v| v.is_a?(String) ? v.strip : v }
|
|
27
|
+
params = params.transform_values { |v| v.is_a?(String) && strip_whitespace ? v.strip : v }
|
|
22
28
|
params.delete_if { |k, v| [*v].all?{ |i| i.blank? && i != false } }
|
|
23
29
|
else
|
|
24
30
|
params = {}
|
|
@@ -42,10 +48,10 @@ module Ransack
|
|
|
42
48
|
collapse_multiparameter_attributes!(params).each do |key, value|
|
|
43
49
|
if ['s'.freeze, 'sorts'.freeze].freeze.include?(key)
|
|
44
50
|
send("#{key}=", value)
|
|
45
|
-
elsif base.attribute_method?(key)
|
|
46
|
-
base.send("#{key}=", value)
|
|
47
51
|
elsif @context.ransackable_scope?(key, @context.object)
|
|
48
52
|
add_scope(key, value)
|
|
53
|
+
elsif base.attribute_method?(key)
|
|
54
|
+
base.send("#{key}=", value)
|
|
49
55
|
elsif !Ransack.options[:ignore_unknown_conditions] || !@ignore_unknown_conditions
|
|
50
56
|
raise ArgumentError, "Invalid search term #{key}"
|
|
51
57
|
end
|
data/lib/ransack/translate.rb
CHANGED
|
@@ -32,6 +32,7 @@ module Ransack
|
|
|
32
32
|
defaults = base_ancestors.map do |klass|
|
|
33
33
|
"ransack.attributes.#{i18n_key(klass)}.#{original_name}".to_sym
|
|
34
34
|
end
|
|
35
|
+
defaults << options.delete(:default) if options[:default]
|
|
35
36
|
|
|
36
37
|
translated_names = attribute_names.map do |name|
|
|
37
38
|
attribute_name(context, name, options[:include_associations])
|
|
@@ -48,7 +49,6 @@ module Ransack
|
|
|
48
49
|
defaults << "%{attributes}".freeze
|
|
49
50
|
end
|
|
50
51
|
|
|
51
|
-
defaults << options.delete(:default) if options[:default]
|
|
52
52
|
options.reverse_merge! count: 1, default: defaults
|
|
53
53
|
I18n.translate(defaults.shift, **options.merge(interpolations))
|
|
54
54
|
end
|
|
@@ -66,7 +66,7 @@ module Ransack
|
|
|
66
66
|
[:"ransack.associations.#{i18n_key(context.klass)}.#{key}"]
|
|
67
67
|
end
|
|
68
68
|
defaults << context.traverse(key).model_name.human
|
|
69
|
-
options = { :
|
|
69
|
+
options = { count: 1, default: defaults }
|
|
70
70
|
I18n.translate(defaults.shift, **options)
|
|
71
71
|
end
|
|
72
72
|
|
|
@@ -149,7 +149,7 @@ module Ransack
|
|
|
149
149
|
end
|
|
150
150
|
|
|
151
151
|
def i18n_key(klass)
|
|
152
|
-
|
|
152
|
+
klass.model_name.i18n_key
|
|
153
153
|
end
|
|
154
154
|
end
|
|
155
155
|
end
|
data/lib/ransack/version.rb
CHANGED
data/lib/ransack/visitor.rb
CHANGED
|
@@ -26,7 +26,14 @@ module Ransack
|
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def visit_and(object)
|
|
29
|
-
|
|
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
|
|
30
37
|
end
|
|
31
38
|
|
|
32
39
|
def visit_or(object)
|
|
@@ -35,17 +42,46 @@ module Ransack
|
|
|
35
42
|
end
|
|
36
43
|
|
|
37
44
|
def quoted?(object)
|
|
38
|
-
|
|
45
|
+
case object
|
|
46
|
+
when Arel::Nodes::SqlLiteral, Bignum, Fixnum
|
|
47
|
+
false
|
|
48
|
+
else
|
|
49
|
+
true
|
|
50
|
+
end
|
|
39
51
|
end
|
|
40
52
|
|
|
41
53
|
def visit(object)
|
|
42
54
|
send(DISPATCH[object.class], object)
|
|
43
55
|
end
|
|
44
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
|
+
|
|
45
70
|
DISPATCH = Hash.new do |hash, klass|
|
|
46
71
|
hash[klass] = "visit_#{
|
|
47
72
|
klass.name.gsub(Constants::TWO_COLONS, Constants::UNDERSCORE)
|
|
48
73
|
}"
|
|
49
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
|
|
50
86
|
end
|
|
51
87
|
end
|
data/lib/ransack.rb
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
require 'active_support/core_ext'
|
|
2
2
|
require 'ransack/configuration'
|
|
3
|
-
require 'ransack/adapters'
|
|
4
3
|
require 'polyamorous/polyamorous'
|
|
5
4
|
|
|
6
|
-
Ransack::Adapters.object_mapper.require_constants
|
|
7
|
-
|
|
8
5
|
module Ransack
|
|
9
6
|
extend Configuration
|
|
10
7
|
class UntraversableAssociationError < StandardError; end
|
|
@@ -12,7 +9,7 @@ end
|
|
|
12
9
|
|
|
13
10
|
Ransack.configure do |config|
|
|
14
11
|
Ransack::Constants::AREL_PREDICATES.each do |name|
|
|
15
|
-
config.add_predicate name, :
|
|
12
|
+
config.add_predicate name, arel_predicate: name
|
|
16
13
|
end
|
|
17
14
|
Ransack::Constants::DERIVED_PREDICATES.each do |args|
|
|
18
15
|
config.add_predicate(*args)
|
|
@@ -22,8 +19,8 @@ end
|
|
|
22
19
|
require 'ransack/search'
|
|
23
20
|
require 'ransack/ransacker'
|
|
24
21
|
require 'ransack/translate'
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
require 'ransack/active_record'
|
|
23
|
+
require 'ransack/context'
|
|
27
24
|
|
|
28
25
|
ActiveSupport.on_load(:action_controller) do
|
|
29
26
|
require 'ransack/helpers'
|
data/ransack.gemspec
CHANGED
|
@@ -7,16 +7,16 @@ Gem::Specification.new do |s|
|
|
|
7
7
|
s.name = "ransack"
|
|
8
8
|
s.version = Ransack::VERSION
|
|
9
9
|
s.platform = Gem::Platform::RUBY
|
|
10
|
-
s.authors = ["Ernie Miller", "Ryan Bigg", "Jon Atack", "Sean Carroll"]
|
|
10
|
+
s.authors = ["Ernie Miller", "Ryan Bigg", "Jon Atack", "Sean Carroll", "David Rodríguez"]
|
|
11
11
|
s.email = ["ernie@erniemiller.org", "radarlistener@gmail.com", "jonnyatack@gmail.com", "sfcarroll@gmail.com"]
|
|
12
12
|
s.homepage = "https://github.com/activerecord-hackery/ransack"
|
|
13
|
-
s.summary = %q{Object-based searching for Active Record
|
|
13
|
+
s.summary = %q{Object-based searching for Active Record.}
|
|
14
14
|
s.description = %q{Ransack is the successor to the MetaSearch gem. It improves and expands upon MetaSearch's functionality, but does not have a 100%-compatible API.}
|
|
15
|
-
s.required_ruby_version = '>= 2.
|
|
15
|
+
s.required_ruby_version = '>= 2.7'
|
|
16
16
|
s.license = 'MIT'
|
|
17
17
|
|
|
18
|
-
s.add_dependency 'activerecord', '>=
|
|
19
|
-
s.add_dependency 'activesupport', '>=
|
|
18
|
+
s.add_dependency 'activerecord', '>= 6.1.5'
|
|
19
|
+
s.add_dependency 'activesupport', '>= 6.1.5'
|
|
20
20
|
s.add_dependency 'i18n'
|
|
21
21
|
|
|
22
22
|
s.files = `git ls-files`.split("\n")
|
|
@@ -3,14 +3,8 @@ module PolyamorousHelper
|
|
|
3
3
|
Polyamorous::JoinAssociation.new reflection, children, klass
|
|
4
4
|
end
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
Polyamorous::JoinDependency.new klass, klass.arel_table, associations, Polyamorous::InnerJoin
|
|
9
|
-
end
|
|
10
|
-
else
|
|
11
|
-
def new_join_dependency(klass, associations = {})
|
|
12
|
-
Polyamorous::JoinDependency.new klass, klass.arel_table, associations
|
|
13
|
-
end
|
|
6
|
+
def new_join_dependency(klass, associations = {})
|
|
7
|
+
Polyamorous::JoinDependency.new klass, klass.arel_table, associations, Polyamorous::InnerJoin
|
|
14
8
|
end
|
|
15
9
|
|
|
16
10
|
def new_join(name, type = Polyamorous::InnerJoin, klass = nil)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Polyamorous
|
|
4
|
+
describe "ActiveRecord Compatibility" do
|
|
5
|
+
it 'works with self joins and includes' do
|
|
6
|
+
trade_account = Account.create!
|
|
7
|
+
Account.create!(trade_account: trade_account)
|
|
8
|
+
|
|
9
|
+
accounts = Account.joins(:trade_account).includes(:trade_account, :agent_account)
|
|
10
|
+
account = accounts.first
|
|
11
|
+
|
|
12
|
+
expect(account.agent_account).to be_nil
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -12,12 +12,7 @@ module Polyamorous
|
|
|
12
12
|
|
|
13
13
|
subject { new_join_association(reflection, parent.children, Person) }
|
|
14
14
|
|
|
15
|
-
it '
|
|
16
|
-
expect(subject).to eq new_join_association(reflection, parent.children, Person)
|
|
17
|
-
expect(subject).not_to eq new_join_association(reflection, parent.children, Article)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
it 'leaves the orginal reflection intact for thread safety' do
|
|
15
|
+
it 'leaves the original reflection intact for thread safety' do
|
|
21
16
|
reflection.instance_variable_set(:@klass, Article)
|
|
22
17
|
join_association
|
|
23
18
|
.swapping_reflection_klass(reflection, Person) do |new_reflection|
|
|
@@ -77,21 +77,5 @@ module Polyamorous
|
|
|
77
77
|
specify { expect(subject.send(:join_root).drop(1)[1].table_name)
|
|
78
78
|
.to eq 'comments' }
|
|
79
79
|
end
|
|
80
|
-
|
|
81
|
-
context '#left_outer_join in Rails 5 overrides join type specified',
|
|
82
|
-
if: ActiveRecord::VERSION::MAJOR >= 5 && ActiveRecord::VERSION::MAJOR < 6 && ActiveRecord::VERSION::MINOR < 2 do
|
|
83
|
-
|
|
84
|
-
let(:join_type_class) do
|
|
85
|
-
new_join_dependency(
|
|
86
|
-
Person,
|
|
87
|
-
new_join(:articles)
|
|
88
|
-
).join_constraints(
|
|
89
|
-
[],
|
|
90
|
-
Arel::Nodes::OuterJoin
|
|
91
|
-
).first.joins.map(&:class)
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
specify { expect(join_type_class).to eq [Arel::Nodes::OuterJoin] }
|
|
95
|
-
end
|
|
96
80
|
end
|
|
97
81
|
end
|