ransack 2.4.2 → 3.2.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/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 +16 -40
- data/.nojekyll +0 -0
- data/CHANGELOG.md +137 -11
- data/CONTRIBUTING.md +4 -3
- data/Gemfile +2 -2
- data/README.md +45 -973
- 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 +284 -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 +107 -0
- data/docs/package.json +37 -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 +7671 -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/polyamorous.rb +1 -0
- data/lib/ransack/adapters/active_record/base.rb +1 -3
- data/lib/ransack/adapters/active_record/context.rb +24 -51
- data/lib/ransack/adapters/active_record/ransack/nodes/condition.rb +2 -9
- data/lib/ransack/configuration.rb +16 -2
- data/lib/ransack/constants.rb +0 -3
- data/lib/ransack/helpers/form_helper.rb +11 -3
- data/lib/ransack/locale/sv.yml +70 -0
- data/lib/ransack/nodes/sort.rb +2 -2
- data/lib/ransack/search.rb +4 -3
- data/lib/ransack/translate.rb +1 -1
- data/lib/ransack/version.rb +1 -1
- 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 +28 -11
- data/spec/ransack/configuration_spec.rb +14 -0
- data/spec/ransack/helpers/form_helper_spec.rb +57 -2
- data/spec/ransack/nodes/condition_spec.rb +13 -0
- data/spec/ransack/search_spec.rb +140 -27
- data/spec/support/schema.rb +49 -0
- metadata +80 -29
- 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/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
|
@@ -1 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
module Polyamorous
|
|
2
|
+
module ReflectionExtensions
|
|
3
|
+
def join_scope(table, foreign_table, foreign_klass)
|
|
4
|
+
if respond_to?(:polymorphic?) && polymorphic?
|
|
5
|
+
super.where!(foreign_table[foreign_type].eq(klass.name))
|
|
6
|
+
else
|
|
7
|
+
super
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'polyamorous/activerecord_6.1_ruby_2/join_association'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'polyamorous/activerecord_6.1_ruby_2/join_dependency'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'polyamorous/activerecord_6.1_ruby_2/reflection'
|
data/lib/polyamorous.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'polyamorous/polyamorous'
|
|
@@ -4,7 +4,6 @@ module Ransack
|
|
|
4
4
|
module Base
|
|
5
5
|
|
|
6
6
|
def self.extended(base)
|
|
7
|
-
alias :search :ransack unless base.respond_to? :search
|
|
8
7
|
base.class_eval do
|
|
9
8
|
class_attribute :_ransackers
|
|
10
9
|
class_attribute :_ransack_aliases
|
|
@@ -14,7 +13,6 @@ module Ransack
|
|
|
14
13
|
end
|
|
15
14
|
|
|
16
15
|
def ransack(params = {}, options = {})
|
|
17
|
-
ActiveSupport::Deprecation.warn("#search is deprecated and will be removed in 2.3, please use #ransack instead") if __callee__ == :search
|
|
18
16
|
Search.new(self, params, options)
|
|
19
17
|
end
|
|
20
18
|
|
|
@@ -70,7 +68,7 @@ module Ransack
|
|
|
70
68
|
end
|
|
71
69
|
|
|
72
70
|
# ransack_scope_skip_sanitize_args, by default, returns an empty array.
|
|
73
|
-
# i.e. use the sanitize_scope_args setting to
|
|
71
|
+
# i.e. use the sanitize_scope_args setting to determine if args should be converted.
|
|
74
72
|
# For overriding with a list of scopes which should be passed the args as-is.
|
|
75
73
|
#
|
|
76
74
|
def ransackable_scopes_skip_sanitize_args
|
|
@@ -44,9 +44,13 @@ module Ransack
|
|
|
44
44
|
else
|
|
45
45
|
case Ransack.options[:postgres_fields_sort_option]
|
|
46
46
|
when :nulls_first
|
|
47
|
-
scope_or_sort = scope_or_sort.direction == :asc ? "#{scope_or_sort.to_sql} NULLS FIRST" : "#{scope_or_sort.to_sql} NULLS LAST"
|
|
47
|
+
scope_or_sort = scope_or_sort.direction == :asc ? Arel.sql("#{scope_or_sort.to_sql} NULLS FIRST") : Arel.sql("#{scope_or_sort.to_sql} NULLS LAST")
|
|
48
48
|
when :nulls_last
|
|
49
|
-
scope_or_sort = scope_or_sort.direction == :asc ? "#{scope_or_sort.to_sql} NULLS LAST" : "#{scope_or_sort.to_sql} NULLS FIRST"
|
|
49
|
+
scope_or_sort = scope_or_sort.direction == :asc ? Arel.sql("#{scope_or_sort.to_sql} NULLS LAST") : Arel.sql("#{scope_or_sort.to_sql} NULLS FIRST")
|
|
50
|
+
when :nulls_always_first
|
|
51
|
+
scope_or_sort = Arel.sql("#{scope_or_sort.to_sql} NULLS FIRST")
|
|
52
|
+
when :nulls_always_last
|
|
53
|
+
scope_or_sort = Arel.sql("#{scope_or_sort.to_sql} NULLS LAST")
|
|
50
54
|
end
|
|
51
55
|
|
|
52
56
|
relation = relation.order(scope_or_sort)
|
|
@@ -106,13 +110,7 @@ module Ransack
|
|
|
106
110
|
def join_sources
|
|
107
111
|
base, joins = begin
|
|
108
112
|
alias_tracker = ::ActiveRecord::Associations::AliasTracker.create(self.klass.connection, @object.table.name, [])
|
|
109
|
-
constraints =
|
|
110
|
-
@join_dependency.join_constraints(@object.joins_values, alias_tracker, @object.references_values)
|
|
111
|
-
elsif ::Gem::Version.new(::ActiveRecord::VERSION::STRING) >= ::Gem::Version.new(Constants::RAILS_6_0)
|
|
112
|
-
@join_dependency.join_constraints(@object.joins_values, alias_tracker)
|
|
113
|
-
else
|
|
114
|
-
@join_dependency.join_constraints(@object.joins_values, @join_type, alias_tracker)
|
|
115
|
-
end
|
|
113
|
+
constraints = @join_dependency.join_constraints(@object.joins_values, alias_tracker, @object.references_values)
|
|
116
114
|
|
|
117
115
|
[
|
|
118
116
|
Arel::SelectManager.new(@object.table),
|
|
@@ -139,6 +137,7 @@ module Ransack
|
|
|
139
137
|
stashed.eql?(association)
|
|
140
138
|
}
|
|
141
139
|
@object.joins_values.delete_if { |jd|
|
|
140
|
+
jd.instance_variables.include?(:@join_root) &&
|
|
142
141
|
jd.instance_variable_get(:@join_root).children.map(&:object_id) == [association.object_id]
|
|
143
142
|
}
|
|
144
143
|
end
|
|
@@ -279,11 +278,7 @@ module Ransack
|
|
|
279
278
|
join_list = join_nodes + convert_join_strings_to_ast(relation.table, string_joins)
|
|
280
279
|
|
|
281
280
|
alias_tracker = ::ActiveRecord::Associations::AliasTracker.create(self.klass.connection, relation.table.name, join_list)
|
|
282
|
-
join_dependency =
|
|
283
|
-
Polyamorous::JoinDependency.new(relation.klass, relation.table, association_joins, Arel::Nodes::OuterJoin)
|
|
284
|
-
else
|
|
285
|
-
Polyamorous::JoinDependency.new(relation.klass, relation.table, association_joins)
|
|
286
|
-
end
|
|
281
|
+
join_dependency = Polyamorous::JoinDependency.new(relation.klass, relation.table, association_joins, Arel::Nodes::OuterJoin)
|
|
287
282
|
join_dependency.instance_variable_set(:@alias_tracker, alias_tracker)
|
|
288
283
|
join_nodes.each do |join|
|
|
289
284
|
join_dependency.send(:alias_tracker).aliases[join.left.name.downcase] = 1
|
|
@@ -310,22 +305,13 @@ module Ransack
|
|
|
310
305
|
end
|
|
311
306
|
|
|
312
307
|
def build_association(name, parent = @base, klass = nil)
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
found_association = jd.instance_variable_get(:@join_root).children.last
|
|
321
|
-
else
|
|
322
|
-
jd = Polyamorous::JoinDependency.new(
|
|
323
|
-
parent.base_klass,
|
|
324
|
-
parent.table,
|
|
325
|
-
Polyamorous::Join.new(name, @join_type, klass)
|
|
326
|
-
)
|
|
327
|
-
found_association = jd.instance_variable_get(:@join_root).children.last
|
|
328
|
-
end
|
|
308
|
+
jd = Polyamorous::JoinDependency.new(
|
|
309
|
+
parent.base_klass,
|
|
310
|
+
parent.table,
|
|
311
|
+
Polyamorous::Join.new(name, @join_type, klass),
|
|
312
|
+
@join_type
|
|
313
|
+
)
|
|
314
|
+
found_association = jd.instance_variable_get(:@join_root).children.last
|
|
329
315
|
|
|
330
316
|
@associations_pot[found_association] = parent
|
|
331
317
|
|
|
@@ -334,11 +320,7 @@ module Ransack
|
|
|
334
320
|
@join_dependency.instance_variable_get(:@join_root).children.push found_association
|
|
335
321
|
|
|
336
322
|
# Builds the arel nodes properly for this association
|
|
337
|
-
|
|
338
|
-
@tables_pot[found_association] = @join_dependency.construct_tables_for_association!(jd.instance_variable_get(:@join_root), found_association)
|
|
339
|
-
else
|
|
340
|
-
@join_dependency.send(:construct_tables!, jd.instance_variable_get(:@join_root))
|
|
341
|
-
end
|
|
323
|
+
@tables_pot[found_association] = @join_dependency.construct_tables_for_association!(jd.instance_variable_get(:@join_root), found_association)
|
|
342
324
|
|
|
343
325
|
# Leverage the stashed association functionality in AR
|
|
344
326
|
@object = @object.joins(jd)
|
|
@@ -348,22 +330,13 @@ module Ransack
|
|
|
348
330
|
def extract_joins(association)
|
|
349
331
|
parent = @join_dependency.instance_variable_get(:@join_root)
|
|
350
332
|
reflection = association.reflection
|
|
351
|
-
join_constraints =
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
)
|
|
359
|
-
else
|
|
360
|
-
association.join_constraints(
|
|
361
|
-
parent.table,
|
|
362
|
-
parent.base_klass,
|
|
363
|
-
Arel::Nodes::OuterJoin,
|
|
364
|
-
@join_dependency.instance_variable_get(:@alias_tracker)
|
|
365
|
-
)
|
|
366
|
-
end
|
|
333
|
+
join_constraints = association.join_constraints_with_tables(
|
|
334
|
+
parent.table,
|
|
335
|
+
parent.base_klass,
|
|
336
|
+
Arel::Nodes::OuterJoin,
|
|
337
|
+
@join_dependency.instance_variable_get(:@alias_tracker),
|
|
338
|
+
@tables_pot[association]
|
|
339
|
+
)
|
|
367
340
|
join_constraints.to_a.flatten
|
|
368
341
|
end
|
|
369
342
|
end
|
|
@@ -47,18 +47,11 @@ module Ransack
|
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
def casted_array?(predicate)
|
|
50
|
-
|
|
51
|
-
(predicate.respond_to?(:val) && predicate.val.is_a?(Array)) # Rails 5.2, 6.0
|
|
50
|
+
predicate.value.is_a?(Array) && predicate.is_a?(Arel::Nodes::Casted)
|
|
52
51
|
end
|
|
53
52
|
|
|
54
53
|
def format_values_for(predicate)
|
|
55
|
-
value
|
|
56
|
-
predicate.value # Rails 6.1
|
|
57
|
-
else
|
|
58
|
-
predicate.val # Rails 5.2, 6.0
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
value.map do |val|
|
|
54
|
+
predicate.value.map do |val|
|
|
62
55
|
val.is_a?(String) ? Arel::Nodes.build_quoted(val) : val
|
|
63
56
|
end
|
|
64
57
|
end
|
|
@@ -34,7 +34,8 @@ module Ransack
|
|
|
34
34
|
:down_arrow => '▲'.freeze,
|
|
35
35
|
:default_arrow => nil,
|
|
36
36
|
:sanitize_scope_args => true,
|
|
37
|
-
:postgres_fields_sort_option => nil
|
|
37
|
+
:postgres_fields_sort_option => nil,
|
|
38
|
+
:strip_whitespace => true
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
def configure
|
|
@@ -148,7 +149,7 @@ module Ransack
|
|
|
148
149
|
# User may want to configure it like this:
|
|
149
150
|
#
|
|
150
151
|
# Ransack.configure do |c|
|
|
151
|
-
# c.postgres_fields_sort_option = :nulls_first # or :
|
|
152
|
+
# c.postgres_fields_sort_option = :nulls_first # or e.g. :nulls_always_last
|
|
152
153
|
# end
|
|
153
154
|
#
|
|
154
155
|
# See this feature: https://www.postgresql.org/docs/13/queries-order.html
|
|
@@ -170,6 +171,19 @@ module Ransack
|
|
|
170
171
|
self.options[:hide_sort_order_indicators] = boolean
|
|
171
172
|
end
|
|
172
173
|
|
|
174
|
+
# By default, Ransack displays strips all whitespace when searching for a string.
|
|
175
|
+
# The default may be globally changed in an initializer file like
|
|
176
|
+
# `config/initializers/ransack.rb` as follows:
|
|
177
|
+
#
|
|
178
|
+
# Ransack.configure do |config|
|
|
179
|
+
# # Enable whitespace stripping for string searches
|
|
180
|
+
# config.strip_whitespace = true
|
|
181
|
+
# end
|
|
182
|
+
#
|
|
183
|
+
def strip_whitespace=(boolean)
|
|
184
|
+
self.options[:strip_whitespace] = boolean
|
|
185
|
+
end
|
|
186
|
+
|
|
173
187
|
def arel_predicate_with_suffix(arel_predicate, suffix)
|
|
174
188
|
if arel_predicate === Proc
|
|
175
189
|
proc { |v| "#{arel_predicate.call(v)}#{suffix}" }
|
data/lib/ransack/constants.rb
CHANGED
|
@@ -45,9 +45,6 @@ module Ransack
|
|
|
45
45
|
NOT_EQ_ALL = 'not_eq_all'.freeze
|
|
46
46
|
CONT = 'cont'.freeze
|
|
47
47
|
|
|
48
|
-
RAILS_6_0 = '6.0.0'.freeze
|
|
49
|
-
RAILS_6_1 = '6.1.0'.freeze
|
|
50
|
-
|
|
51
48
|
RANSACK_SLASH_SEARCHES = 'ransack/searches'.freeze
|
|
52
49
|
RANSACK_SLASH_SEARCHES_SLASH_SEARCH = 'ransack/searches/search'.freeze
|
|
53
50
|
end
|
|
@@ -130,12 +130,20 @@ module Ransack
|
|
|
130
130
|
|
|
131
131
|
def url_options
|
|
132
132
|
@params.merge(
|
|
133
|
-
@options.merge(
|
|
133
|
+
@options.except(:class, :data, :host).merge(
|
|
134
134
|
@search.context.search_key => search_and_sort_params))
|
|
135
135
|
end
|
|
136
136
|
|
|
137
137
|
def html_options(args)
|
|
138
|
-
|
|
138
|
+
if args.empty?
|
|
139
|
+
html_options = @options
|
|
140
|
+
else
|
|
141
|
+
deprecation_message = "Passing two trailing hashes to `sort_link` is deprecated, merge the trailing hashes into a single one."
|
|
142
|
+
caller_location = caller_locations(2, 2).first
|
|
143
|
+
warn "#{deprecation_message} (called at #{caller_location.path}:#{caller_location.lineno})"
|
|
144
|
+
html_options = extract_options_and_mutate_args!(args)
|
|
145
|
+
end
|
|
146
|
+
|
|
139
147
|
html_options.merge(
|
|
140
148
|
class: [['sort_link'.freeze, @current_dir], html_options[:class]]
|
|
141
149
|
.compact.join(' '.freeze)
|
|
@@ -145,7 +153,7 @@ module Ransack
|
|
|
145
153
|
private
|
|
146
154
|
|
|
147
155
|
def parameters_hash(params)
|
|
148
|
-
if
|
|
156
|
+
if params.respond_to?(:to_unsafe_h)
|
|
149
157
|
params.to_unsafe_h
|
|
150
158
|
else
|
|
151
159
|
params
|
|
@@ -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"
|
data/lib/ransack/nodes/sort.rb
CHANGED
data/lib/ransack/search.rb
CHANGED
|
@@ -15,10 +15,11 @@ module Ransack
|
|
|
15
15
|
:translate, :to => :base
|
|
16
16
|
|
|
17
17
|
def initialize(object, params = {}, options = {})
|
|
18
|
+
strip_whitespace = options.fetch(:strip_whitespace, Ransack.options[:strip_whitespace])
|
|
18
19
|
params = params.to_unsafe_h if params.respond_to?(:to_unsafe_h)
|
|
19
20
|
if params.is_a? Hash
|
|
20
21
|
params = params.dup
|
|
21
|
-
params = params.transform_values { |v| v.is_a?(String) ? v.strip : v }
|
|
22
|
+
params = params.transform_values { |v| v.is_a?(String) && strip_whitespace ? v.strip : v }
|
|
22
23
|
params.delete_if { |k, v| [*v].all?{ |i| i.blank? && i != false } }
|
|
23
24
|
else
|
|
24
25
|
params = {}
|
|
@@ -42,10 +43,10 @@ module Ransack
|
|
|
42
43
|
collapse_multiparameter_attributes!(params).each do |key, value|
|
|
43
44
|
if ['s'.freeze, 'sorts'.freeze].freeze.include?(key)
|
|
44
45
|
send("#{key}=", value)
|
|
45
|
-
elsif base.attribute_method?(key)
|
|
46
|
-
base.send("#{key}=", value)
|
|
47
46
|
elsif @context.ransackable_scope?(key, @context.object)
|
|
48
47
|
add_scope(key, value)
|
|
48
|
+
elsif base.attribute_method?(key)
|
|
49
|
+
base.send("#{key}=", value)
|
|
49
50
|
elsif !Ransack.options[:ignore_unknown_conditions] || !@ignore_unknown_conditions
|
|
50
51
|
raise ArgumentError, "Invalid search term #{key}"
|
|
51
52
|
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
|
data/lib/ransack/version.rb
CHANGED
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
|
|
@@ -8,7 +8,6 @@ module Ransack
|
|
|
8
8
|
subject { ::ActiveRecord::Base }
|
|
9
9
|
|
|
10
10
|
it { should respond_to :ransack }
|
|
11
|
-
it { should respond_to :search }
|
|
12
11
|
|
|
13
12
|
describe '#search' do
|
|
14
13
|
subject { Person.ransack }
|
|
@@ -44,12 +43,12 @@ module Ransack
|
|
|
44
43
|
|
|
45
44
|
it 'applies stringy boolean scopes with true value in an array' do
|
|
46
45
|
s = Person.ransack('of_age' => ['true'])
|
|
47
|
-
expect(s.result.to_sql).to (include 'age >= 18')
|
|
46
|
+
expect(s.result.to_sql).to (include rails7_and_mysql ? %q{(age >= '18')} : 'age >= 18')
|
|
48
47
|
end
|
|
49
48
|
|
|
50
49
|
it 'applies stringy boolean scopes with false value in an array' do
|
|
51
50
|
s = Person.ransack('of_age' => ['false'])
|
|
52
|
-
expect(s.result.to_sql).to (include 'age < 18')
|
|
51
|
+
expect(s.result.to_sql).to (include rails7_and_mysql ? %q{age < '18'} : 'age < 18')
|
|
53
52
|
end
|
|
54
53
|
|
|
55
54
|
it 'ignores unlisted scopes' do
|
|
@@ -69,15 +68,25 @@ module Ransack
|
|
|
69
68
|
|
|
70
69
|
it 'passes values to scopes' do
|
|
71
70
|
s = Person.ransack('over_age' => 18)
|
|
72
|
-
expect(s.result.to_sql).to (include 'age > 18')
|
|
71
|
+
expect(s.result.to_sql).to (include rails7_and_mysql ? %q{age > '18'} : 'age > 18')
|
|
73
72
|
end
|
|
74
73
|
|
|
75
74
|
it 'chains scopes' do
|
|
76
75
|
s = Person.ransack('over_age' => 18, 'active' => true)
|
|
77
|
-
expect(s.result.to_sql).to (include 'age > 18')
|
|
76
|
+
expect(s.result.to_sql).to (include rails7_and_mysql ? %q{age > '18'} : 'age > 18')
|
|
78
77
|
expect(s.result.to_sql).to (include 'active = 1')
|
|
79
78
|
end
|
|
80
79
|
|
|
80
|
+
it 'applies scopes that define string SQL joins' do
|
|
81
|
+
allow(Article)
|
|
82
|
+
.to receive(:ransackable_scopes)
|
|
83
|
+
.and_return([:latest_comment_cont])
|
|
84
|
+
|
|
85
|
+
# Including a negative condition to test removing the scope
|
|
86
|
+
s = Search.new(Article, notes_note_not_eq: 'Test', latest_comment_cont: 'Test')
|
|
87
|
+
expect(s.result.to_sql).to include 'latest_comment'
|
|
88
|
+
end
|
|
89
|
+
|
|
81
90
|
context "with sanitize_custom_scope_booleans set to false" do
|
|
82
91
|
before(:all) do
|
|
83
92
|
Ransack.configure { |c| c.sanitize_custom_scope_booleans = false }
|
|
@@ -89,12 +98,12 @@ module Ransack
|
|
|
89
98
|
|
|
90
99
|
it 'passes true values to scopes' do
|
|
91
100
|
s = Person.ransack('over_age' => 1)
|
|
92
|
-
expect(s.result.to_sql).to (include 'age > 1')
|
|
101
|
+
expect(s.result.to_sql).to (include rails7_and_mysql ? %q{age > '1'} : 'age > 1')
|
|
93
102
|
end
|
|
94
103
|
|
|
95
104
|
it 'passes false values to scopes' do
|
|
96
105
|
s = Person.ransack('over_age' => 0)
|
|
97
|
-
expect(s.result.to_sql).to (include 'age > 0')
|
|
106
|
+
expect(s.result.to_sql).to (include rails7_and_mysql ? %q{age > '0'} : 'age > 0')
|
|
98
107
|
end
|
|
99
108
|
end
|
|
100
109
|
|
|
@@ -107,12 +116,12 @@ module Ransack
|
|
|
107
116
|
|
|
108
117
|
it 'passes true values to scopes' do
|
|
109
118
|
s = Person.ransack('over_age' => 1)
|
|
110
|
-
expect(s.result.to_sql).to (include 'age > 1')
|
|
119
|
+
expect(s.result.to_sql).to (include rails7_and_mysql ? %q{age > '1'} : 'age > 1')
|
|
111
120
|
end
|
|
112
121
|
|
|
113
122
|
it 'passes false values to scopes' do
|
|
114
123
|
s = Person.ransack('over_age' => 0)
|
|
115
|
-
expect(s.result.to_sql).to (include 'age > 0')
|
|
124
|
+
expect(s.result.to_sql).to (include rails7_and_mysql ? %q{age > '0'} : 'age > 0')
|
|
116
125
|
end
|
|
117
126
|
end
|
|
118
127
|
|
|
@@ -123,7 +132,7 @@ module Ransack
|
|
|
123
132
|
end
|
|
124
133
|
|
|
125
134
|
it 'raises exception if ransack! called with unknown condition' do
|
|
126
|
-
expect { Person.ransack!(unknown_attr_eq: 'Ernie') }.to raise_error
|
|
135
|
+
expect { Person.ransack!(unknown_attr_eq: 'Ernie') }.to raise_error(ArgumentError)
|
|
127
136
|
end
|
|
128
137
|
|
|
129
138
|
it 'does not modify the parameters' do
|
|
@@ -314,7 +323,11 @@ module Ransack
|
|
|
314
323
|
end
|
|
315
324
|
|
|
316
325
|
it 'should function correctly with a multi-parameter attribute' do
|
|
317
|
-
::ActiveRecord::
|
|
326
|
+
if ::ActiveRecord::VERSION::MAJOR >= 7
|
|
327
|
+
::ActiveRecord.default_timezone = :utc
|
|
328
|
+
else
|
|
329
|
+
::ActiveRecord::Base.default_timezone = :utc
|
|
330
|
+
end
|
|
318
331
|
Time.zone = 'UTC'
|
|
319
332
|
|
|
320
333
|
date = Date.current
|
|
@@ -690,6 +703,10 @@ module Ransack
|
|
|
690
703
|
it { should eq [] }
|
|
691
704
|
end
|
|
692
705
|
|
|
706
|
+
private
|
|
707
|
+
def rails7_and_mysql
|
|
708
|
+
::ActiveRecord::VERSION::MAJOR >= 7 && ENV['DB'] == 'mysql'
|
|
709
|
+
end
|
|
693
710
|
end
|
|
694
711
|
end
|
|
695
712
|
end
|
|
@@ -45,6 +45,20 @@ module Ransack
|
|
|
45
45
|
Ransack.options = default
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
+
it 'should have default value for strip_whitespace' do
|
|
49
|
+
expect(Ransack.options[:strip_whitespace]).to eq true
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'changes default search key parameter' do
|
|
53
|
+
default = Ransack.options.clone
|
|
54
|
+
|
|
55
|
+
Ransack.configure { |c| c.strip_whitespace = false }
|
|
56
|
+
|
|
57
|
+
expect(Ransack.options[:strip_whitespace]).to eq false
|
|
58
|
+
|
|
59
|
+
Ransack.options = default
|
|
60
|
+
end
|
|
61
|
+
|
|
48
62
|
it 'should have default values for arrows' do
|
|
49
63
|
expect(Ransack.options[:up_arrow]).to eq '▼'
|
|
50
64
|
expect(Ransack.options[:down_arrow]).to eq '▲'
|