ransack 2.4.2 → 2.5.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/rubocop.yml +1 -1
- data/.github/workflows/test.yml +31 -22
- data/CHANGELOG.md +10 -1
- data/CONTRIBUTING.md +3 -0
- data/README.md +75 -9
- data/docs/release_process.md +2 -5
- 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/polyamorous.rb +1 -0
- data/lib/ransack/adapters/active_record/base.rb +1 -1
- data/lib/ransack/adapters/active_record/context.rb +6 -2
- data/lib/ransack/adapters/active_record/ransack/nodes/condition.rb +10 -9
- data/lib/ransack/configuration.rb +16 -2
- data/lib/ransack/locale/sv.yml +70 -0
- data/lib/ransack/nodes/sort.rb +2 -2
- data/lib/ransack/search.rb +2 -1
- data/lib/ransack/translate.rb +1 -1
- data/lib/ransack/version.rb +1 -1
- data/spec/polyamorous/join_association_spec.rb +1 -1
- data/spec/ransack/adapters/active_record/base_spec.rb +18 -10
- data/spec/ransack/configuration_spec.rb +14 -0
- data/spec/ransack/nodes/condition_spec.rb +13 -0
- data/spec/ransack/search_spec.rb +117 -27
- data/spec/support/schema.rb +23 -0
- metadata +11 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 27d9d0b5ebf5727ab6405767c7b545ae6afc6b6dc1ff6eec441d0108cea8cb11
|
|
4
|
+
data.tar.gz: b1cd5f875a4c29434efdcaee2a1b47c9ba7fefacba802f6cac0f6c75545cc912
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '0961ec1b9a3874dfd1242d40bae780b1f5a553e418a7bdcd1e599c5a25768831ce22b12c861a2c703beb2ad157751429aa034de1769ef3c83a8837b27356f679'
|
|
7
|
+
data.tar.gz: 7483453ea26b635323d153bd632f8c38ef03d24ca674b5266f62a870f29d7e395b81c678ae7403dd6b54b27985203e12c80701a0e990d47dcdeacc6c8b1d5aa6
|
|
@@ -11,9 +11,8 @@ jobs:
|
|
|
11
11
|
fail-fast: false
|
|
12
12
|
matrix:
|
|
13
13
|
ruby:
|
|
14
|
-
- 3.0.
|
|
15
|
-
- 2.7.
|
|
16
|
-
- 2.6.6
|
|
14
|
+
- 3.0.2
|
|
15
|
+
- 2.7.4
|
|
17
16
|
env:
|
|
18
17
|
DB: sqlite3
|
|
19
18
|
RAILS: main
|
|
@@ -34,9 +33,8 @@ jobs:
|
|
|
34
33
|
fail-fast: false
|
|
35
34
|
matrix:
|
|
36
35
|
ruby:
|
|
37
|
-
- 3.0.
|
|
38
|
-
- 2.7.
|
|
39
|
-
- 2.6.6
|
|
36
|
+
- 3.0.2
|
|
37
|
+
- 2.7.4
|
|
40
38
|
env:
|
|
41
39
|
DB: mysql
|
|
42
40
|
RAILS: main
|
|
@@ -66,9 +64,8 @@ jobs:
|
|
|
66
64
|
fail-fast: false
|
|
67
65
|
matrix:
|
|
68
66
|
ruby:
|
|
69
|
-
- 3.0.
|
|
70
|
-
- 2.7.
|
|
71
|
-
- 2.6.6
|
|
67
|
+
- 3.0.2
|
|
68
|
+
- 2.7.4
|
|
72
69
|
env:
|
|
73
70
|
DB: postgres
|
|
74
71
|
RAILS: main
|
data/.github/workflows/test.yml
CHANGED
|
@@ -11,20 +11,23 @@ jobs:
|
|
|
11
11
|
fail-fast: false
|
|
12
12
|
matrix:
|
|
13
13
|
rails:
|
|
14
|
-
-
|
|
15
|
-
- v6.
|
|
14
|
+
- v7.0.0
|
|
15
|
+
- v6.1.4
|
|
16
|
+
- v6.0.4
|
|
16
17
|
- 6-0-stable
|
|
17
18
|
- 5-2-stable
|
|
18
19
|
- v5.2.4
|
|
19
20
|
ruby:
|
|
20
|
-
- 3.0.
|
|
21
|
-
- 2.7.
|
|
22
|
-
- 2.6.
|
|
21
|
+
- 3.0.2
|
|
22
|
+
- 2.7.4
|
|
23
|
+
- 2.6.7
|
|
23
24
|
exclude:
|
|
25
|
+
- rails: v7.0.0
|
|
26
|
+
ruby: 2.6.7
|
|
24
27
|
- rails: v5.2.4
|
|
25
|
-
ruby: 3.0.
|
|
28
|
+
ruby: 3.0.2
|
|
26
29
|
- rails: 5-2-stable
|
|
27
|
-
ruby: 3.0.
|
|
30
|
+
ruby: 3.0.2
|
|
28
31
|
env:
|
|
29
32
|
DB: sqlite3
|
|
30
33
|
RAILS: ${{ matrix.rails }}
|
|
@@ -45,20 +48,23 @@ jobs:
|
|
|
45
48
|
fail-fast: false
|
|
46
49
|
matrix:
|
|
47
50
|
rails:
|
|
48
|
-
-
|
|
49
|
-
- v6.
|
|
51
|
+
- v7.0.0
|
|
52
|
+
- v6.1.4
|
|
53
|
+
- v6.0.4
|
|
50
54
|
- 6-0-stable
|
|
51
55
|
- 5-2-stable
|
|
52
56
|
- v5.2.4
|
|
53
57
|
ruby:
|
|
54
|
-
- 3.0.
|
|
55
|
-
- 2.7.
|
|
56
|
-
- 2.6.
|
|
58
|
+
- 3.0.2
|
|
59
|
+
- 2.7.4
|
|
60
|
+
- 2.6.7
|
|
57
61
|
exclude:
|
|
62
|
+
- rails: v7.0.0
|
|
63
|
+
ruby: 2.6.7
|
|
58
64
|
- rails: v5.2.4
|
|
59
|
-
ruby: 3.0.
|
|
65
|
+
ruby: 3.0.2
|
|
60
66
|
- rails: 5-2-stable
|
|
61
|
-
ruby: 3.0.
|
|
67
|
+
ruby: 3.0.2
|
|
62
68
|
env:
|
|
63
69
|
DB: mysql
|
|
64
70
|
RAILS: ${{ matrix.rails }}
|
|
@@ -88,20 +94,23 @@ jobs:
|
|
|
88
94
|
fail-fast: false
|
|
89
95
|
matrix:
|
|
90
96
|
rails:
|
|
91
|
-
-
|
|
92
|
-
- v6.
|
|
97
|
+
- v7.0.0
|
|
98
|
+
- v6.1.4
|
|
99
|
+
- v6.0.4
|
|
93
100
|
- 6-0-stable
|
|
94
101
|
- 5-2-stable
|
|
95
102
|
- v5.2.4
|
|
96
103
|
ruby:
|
|
97
|
-
- 3.0.
|
|
98
|
-
- 2.7.
|
|
99
|
-
- 2.6.
|
|
104
|
+
- 3.0.2
|
|
105
|
+
- 2.7.4
|
|
106
|
+
- 2.6.7
|
|
100
107
|
exclude:
|
|
108
|
+
- rails: v7.0.0
|
|
109
|
+
ruby: 2.6.7
|
|
101
110
|
- rails: v5.2.4
|
|
102
|
-
ruby: 3.0.
|
|
111
|
+
ruby: 3.0.2
|
|
103
112
|
- rails: 5-2-stable
|
|
104
|
-
ruby: 3.0.
|
|
113
|
+
ruby: 3.0.2
|
|
105
114
|
env:
|
|
106
115
|
DB: postgres
|
|
107
116
|
RAILS: ${{ matrix.rails }}
|
|
@@ -144,7 +153,7 @@ jobs:
|
|
|
144
153
|
- name: Set up Ruby
|
|
145
154
|
uses: ruby/setup-ruby@v1
|
|
146
155
|
with:
|
|
147
|
-
ruby-version: 3.0.
|
|
156
|
+
ruby-version: 3.0.2
|
|
148
157
|
- name: Install dependencies
|
|
149
158
|
run: bundle install
|
|
150
159
|
- name: Run bug report templates
|
data/CHANGELOG.md
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## 2.5.0 - 2021-12-26
|
|
6
|
+
|
|
7
|
+
* ActiveRecord 7.0 support
|
|
8
|
+
|
|
3
9
|
* Drop support for rubies under 2.5. PR #1189
|
|
4
10
|
|
|
11
|
+
* Have casted array predicates type checked to Arel::Nodes::Casted fixing non-casted array predicates.
|
|
12
|
+
PR [1246](https://github.com/activerecord-hackery/ransack/pull/1246)
|
|
13
|
+
|
|
5
14
|
## 2.4.1 - 2020-12-21
|
|
6
15
|
|
|
7
16
|
* Add `ActiveRecord::Base.ransack!` which raises error if passed unknown condition
|
|
@@ -200,7 +209,7 @@
|
|
|
200
209
|
ignored when block parameter is specified.
|
|
201
210
|
PR [#818](https://github.com/activerecord-hackery/ransack/pull/818).
|
|
202
211
|
|
|
203
|
-
* No need pass some
|
|
212
|
+
* No need pass some arguments to JoinAssociation#join_constraints in Rails 5.1.
|
|
204
213
|
PR [#814](https://github.com/activerecord-hackery/ransack/pull/814).
|
|
205
214
|
Fixes [#807](https://github.com/activerecord-hackery/ransack/issues/807).
|
|
206
215
|
Reference [rails/rails#28267](https://github.com/rails/rails/pull/28267)
|
data/CONTRIBUTING.md
CHANGED
|
@@ -115,6 +115,9 @@ Here's a quick guide:
|
|
|
115
115
|
$ git config --global user.email "contributor@example.com"
|
|
116
116
|
|
|
117
117
|
10. Commit your changes (`git commit -am 'Add feature/fix bug/improve docs'`).
|
|
118
|
+
If your pull request only contains documentation changes, please remember
|
|
119
|
+
to add `[skip ci]` to the beginning of your commit message so the CI
|
|
120
|
+
test suite doesn't :runner: needlessly.
|
|
118
121
|
|
|
119
122
|
11. If necessary, rebase your commits into logical chunks, without errors. To
|
|
120
123
|
interactively rebase and cherry-pick from, say, the last 10 commits:
|
data/README.md
CHANGED
|
@@ -11,9 +11,7 @@ Ransack enables the creation of both
|
|
|
11
11
|
for your Ruby on Rails application
|
|
12
12
|
([demo source code here](https://github.com/activerecord-hackery/ransack_demo)).
|
|
13
13
|
If you're looking for something that simplifies query generation at the model
|
|
14
|
-
or controller layer, you're probably not looking for Ransack
|
|
15
|
-
for that matter). Try [Squeel](https://github.com/activerecord-hackery/squeel)
|
|
16
|
-
instead.
|
|
14
|
+
or controller layer, you're probably not looking for Ransack.
|
|
17
15
|
|
|
18
16
|
## Getting started
|
|
19
17
|
|
|
@@ -65,19 +63,18 @@ this example, with preloading each Person's Articles and pagination):
|
|
|
65
63
|
def index
|
|
66
64
|
@q = Person.ransack(params[:q])
|
|
67
65
|
@people = @q.result.includes(:articles).page(params[:page])
|
|
68
|
-
|
|
69
|
-
# or use `to_a.uniq` to remove duplicates (can also be done in the view):
|
|
70
|
-
@people = @q.result.includes(:articles).page(params[:page]).to_a.uniq
|
|
71
66
|
end
|
|
72
67
|
```
|
|
73
68
|
|
|
74
|
-
##### Default search
|
|
69
|
+
##### Default search options
|
|
70
|
+
|
|
71
|
+
**Search parameter**
|
|
75
72
|
|
|
76
73
|
Ransack uses a default `:q` param key for search params. This may be changed by
|
|
77
74
|
setting the `search_key` option in a Ransack initializer file (typically
|
|
78
75
|
`config/initializers/ransack.rb`):
|
|
79
76
|
|
|
80
|
-
```
|
|
77
|
+
```ruby
|
|
81
78
|
Ransack.configure do |c|
|
|
82
79
|
# Change default search parameter key name.
|
|
83
80
|
# Default key name is :q
|
|
@@ -85,6 +82,19 @@ Ransack.configure do |c|
|
|
|
85
82
|
end
|
|
86
83
|
```
|
|
87
84
|
|
|
85
|
+
**String search**
|
|
86
|
+
|
|
87
|
+
After version 2.4.0 when searching a string query Ransack by default strips all whitespace around the query string.
|
|
88
|
+
This may be disabled by setting the `strip_whitespace` option in a Ransack initializer file:
|
|
89
|
+
|
|
90
|
+
```ruby
|
|
91
|
+
Ransack.configure do |c|
|
|
92
|
+
# Change whitespace stripping behaviour.
|
|
93
|
+
# Default is true
|
|
94
|
+
c.strip_whitespace = false
|
|
95
|
+
end
|
|
96
|
+
```
|
|
97
|
+
|
|
88
98
|
#### In your view
|
|
89
99
|
|
|
90
100
|
The two primary Ransack view helpers are `search_form_for` and `sort_link`,
|
|
@@ -263,8 +273,45 @@ Ransack.configure do |c|
|
|
|
263
273
|
end
|
|
264
274
|
```
|
|
265
275
|
|
|
276
|
+
To treat nulls as having the lowest or highest value respectively. To force nulls to always be first or last, use
|
|
277
|
+
|
|
278
|
+
```rb
|
|
279
|
+
Ransack.configure do |c|
|
|
280
|
+
c.postgres_fields_sort_option = :nulls_always_first # or :nulls_always_last
|
|
281
|
+
end
|
|
282
|
+
```
|
|
283
|
+
|
|
266
284
|
See this feature: https://www.postgresql.org/docs/13/queries-order.html
|
|
267
285
|
|
|
286
|
+
#### Case Insensitive Sorting in PostgreSQL
|
|
287
|
+
|
|
288
|
+
In order to request PostgreSQL to do a case insensitive sort for all string columns of a model at once, Ransack can be extended by using this approach:
|
|
289
|
+
|
|
290
|
+
```ruby
|
|
291
|
+
module RansackObject
|
|
292
|
+
|
|
293
|
+
def self.included(base)
|
|
294
|
+
base.columns.each do |column|
|
|
295
|
+
if column.type == :string
|
|
296
|
+
base.ransacker column.name.to_sym, type: :string do
|
|
297
|
+
Arel.sql("lower(#{base.table_name}.#{column.name})")
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
```ruby
|
|
306
|
+
class UserWithManyAttributes < ActiveRecord::Base
|
|
307
|
+
include RansackObject
|
|
308
|
+
end
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
If this approach is taken, it is advisable to [add a functional index](https://www.postgresql.org/docs/13/citext.html).
|
|
312
|
+
|
|
313
|
+
This was originally asked in [a Ransack issue](https://github.com/activerecord-hackery/ransack/issues/1201) and a solution was found on [Stack Overflow](https://stackoverflow.com/a/34677378).
|
|
314
|
+
|
|
268
315
|
### Advanced Mode
|
|
269
316
|
|
|
270
317
|
"Advanced" searches (ab)use Rails' nested attributes functionality in order to
|
|
@@ -423,6 +470,25 @@ query parameters in your URLs.
|
|
|
423
470
|
<% end %>
|
|
424
471
|
```
|
|
425
472
|
|
|
473
|
+
You can also use `ransack_alias` for sorting.
|
|
474
|
+
|
|
475
|
+
```ruby
|
|
476
|
+
class Post < ActiveRecord::Base
|
|
477
|
+
belongs_to :author
|
|
478
|
+
|
|
479
|
+
# Abbreviate :author_first_name to :author
|
|
480
|
+
ransack_alias :author, :author_first_name
|
|
481
|
+
end
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
Now, you can use `:author` instead of `:author_first_name` in a `sort_link`.
|
|
485
|
+
|
|
486
|
+
```erb
|
|
487
|
+
<%= sort_link(@q, :author) %>
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
Note that using `:author_first_name_or_author_last_name_cont` would produce an invalid sql query. In those cases, Ransack ignores the sorting clause.
|
|
491
|
+
|
|
426
492
|
### Search Matchers
|
|
427
493
|
|
|
428
494
|
List of all possible predicates
|
|
@@ -719,7 +785,7 @@ Article.ransack!(unknown_attr_eq: 'Ernie')
|
|
|
719
785
|
# ArgumentError: Invalid search term unknown_attr_eq
|
|
720
786
|
```
|
|
721
787
|
|
|
722
|
-
This is
|
|
788
|
+
This is equivalent to the `ignore_unknown_conditions` configuration option,
|
|
723
789
|
except it may be applied on a case-by-case basis.
|
|
724
790
|
|
|
725
791
|
### Using Scopes/Class Methods
|
data/docs/release_process.md
CHANGED
|
@@ -5,12 +5,9 @@
|
|
|
5
5
|
To release a new version of Ransack and publish it to RubyGems, take the following steps:
|
|
6
6
|
|
|
7
7
|
- Create a new release, marked `Prerelease`.
|
|
8
|
-
<<<<<<< Updated upstream
|
|
9
8
|
- Update the versions file to the new release, commit and push to `master`.
|
|
10
|
-
|
|
11
|
-
-
|
|
12
|
-
>>>>>>> Stashed changes
|
|
13
|
-
- From the terminal, run the following commands
|
|
9
|
+
- Update the [`version.rb`](../lib/ransack/version.rb) file to the new release, commit and push to `master`.
|
|
10
|
+
- From the terminal, run the following commands:
|
|
14
11
|
|
|
15
12
|
```bash
|
|
16
13
|
rake build
|
data/lib/polyamorous/{activerecord_6.2_ruby_2 → activerecord_7.0_ruby_2}/join_association.rb
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
data/lib/polyamorous.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'polyamorous/polyamorous'
|
|
@@ -70,7 +70,7 @@ module Ransack
|
|
|
70
70
|
end
|
|
71
71
|
|
|
72
72
|
# ransack_scope_skip_sanitize_args, by default, returns an empty array.
|
|
73
|
-
# i.e. use the sanitize_scope_args setting to
|
|
73
|
+
# i.e. use the sanitize_scope_args setting to determine if args should be converted.
|
|
74
74
|
# For overriding with a list of scopes which should be passed the args as-is.
|
|
75
75
|
#
|
|
76
76
|
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)
|
|
@@ -47,18 +47,19 @@ module Ransack
|
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
def casted_array?(predicate)
|
|
50
|
-
(predicate.
|
|
51
|
-
(predicate.respond_to?(:val) && predicate.val.is_a?(Array)) # Rails 5.2, 6.0
|
|
50
|
+
value_from(predicate).is_a?(Array) && predicate.is_a?(Arel::Nodes::Casted)
|
|
52
51
|
end
|
|
53
52
|
|
|
54
|
-
def
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
53
|
+
def value_from(predicate)
|
|
54
|
+
if predicate.respond_to?(:value)
|
|
55
|
+
predicate.value # Rails 6.1
|
|
56
|
+
elsif predicate.respond_to?(:val)
|
|
57
|
+
predicate.val # Rails 5.2, 6.0
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
def format_values_for(predicate)
|
|
62
|
+
value_from(predicate).map do |val|
|
|
62
63
|
val.is_a?(String) ? Arel::Nodes.build_quoted(val) : val
|
|
63
64
|
end
|
|
64
65
|
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}" }
|
|
@@ -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 = {}
|
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
|
@@ -17,7 +17,7 @@ module Polyamorous
|
|
|
17
17
|
expect(subject).not_to eq new_join_association(reflection, parent.children, Article)
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
it 'leaves the
|
|
20
|
+
it 'leaves the original reflection intact for thread safety' do
|
|
21
21
|
reflection.instance_variable_set(:@klass, Article)
|
|
22
22
|
join_association
|
|
23
23
|
.swapping_reflection_klass(reflection, Person) do |new_reflection|
|
|
@@ -44,12 +44,12 @@ module Ransack
|
|
|
44
44
|
|
|
45
45
|
it 'applies stringy boolean scopes with true value in an array' do
|
|
46
46
|
s = Person.ransack('of_age' => ['true'])
|
|
47
|
-
expect(s.result.to_sql).to (include 'age >= 18')
|
|
47
|
+
expect(s.result.to_sql).to (include rails7_and_mysql ? %q{(age >= '18')} : 'age >= 18')
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
it 'applies stringy boolean scopes with false value in an array' do
|
|
51
51
|
s = Person.ransack('of_age' => ['false'])
|
|
52
|
-
expect(s.result.to_sql).to (include 'age < 18')
|
|
52
|
+
expect(s.result.to_sql).to (include rails7_and_mysql ? %q{age < '18'} : 'age < 18')
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
it 'ignores unlisted scopes' do
|
|
@@ -69,12 +69,12 @@ module Ransack
|
|
|
69
69
|
|
|
70
70
|
it 'passes values to scopes' do
|
|
71
71
|
s = Person.ransack('over_age' => 18)
|
|
72
|
-
expect(s.result.to_sql).to (include 'age > 18')
|
|
72
|
+
expect(s.result.to_sql).to (include rails7_and_mysql ? %q{age > '18'} : 'age > 18')
|
|
73
73
|
end
|
|
74
74
|
|
|
75
75
|
it 'chains scopes' do
|
|
76
76
|
s = Person.ransack('over_age' => 18, 'active' => true)
|
|
77
|
-
expect(s.result.to_sql).to (include 'age > 18')
|
|
77
|
+
expect(s.result.to_sql).to (include rails7_and_mysql ? %q{age > '18'} : 'age > 18')
|
|
78
78
|
expect(s.result.to_sql).to (include 'active = 1')
|
|
79
79
|
end
|
|
80
80
|
|
|
@@ -89,12 +89,12 @@ module Ransack
|
|
|
89
89
|
|
|
90
90
|
it 'passes true values to scopes' do
|
|
91
91
|
s = Person.ransack('over_age' => 1)
|
|
92
|
-
expect(s.result.to_sql).to (include 'age > 1')
|
|
92
|
+
expect(s.result.to_sql).to (include rails7_and_mysql ? %q{age > '1'} : 'age > 1')
|
|
93
93
|
end
|
|
94
94
|
|
|
95
95
|
it 'passes false values to scopes' do
|
|
96
96
|
s = Person.ransack('over_age' => 0)
|
|
97
|
-
expect(s.result.to_sql).to (include 'age > 0')
|
|
97
|
+
expect(s.result.to_sql).to (include rails7_and_mysql ? %q{age > '0'} : 'age > 0')
|
|
98
98
|
end
|
|
99
99
|
end
|
|
100
100
|
|
|
@@ -107,12 +107,12 @@ module Ransack
|
|
|
107
107
|
|
|
108
108
|
it 'passes true values to scopes' do
|
|
109
109
|
s = Person.ransack('over_age' => 1)
|
|
110
|
-
expect(s.result.to_sql).to (include 'age > 1')
|
|
110
|
+
expect(s.result.to_sql).to (include rails7_and_mysql ? %q{age > '1'} : 'age > 1')
|
|
111
111
|
end
|
|
112
112
|
|
|
113
113
|
it 'passes false values to scopes' do
|
|
114
114
|
s = Person.ransack('over_age' => 0)
|
|
115
|
-
expect(s.result.to_sql).to (include 'age > 0')
|
|
115
|
+
expect(s.result.to_sql).to (include rails7_and_mysql ? %q{age > '0'} : 'age > 0')
|
|
116
116
|
end
|
|
117
117
|
end
|
|
118
118
|
|
|
@@ -123,7 +123,7 @@ module Ransack
|
|
|
123
123
|
end
|
|
124
124
|
|
|
125
125
|
it 'raises exception if ransack! called with unknown condition' do
|
|
126
|
-
expect { Person.ransack!(unknown_attr_eq: 'Ernie') }.to raise_error
|
|
126
|
+
expect { Person.ransack!(unknown_attr_eq: 'Ernie') }.to raise_error(ArgumentError)
|
|
127
127
|
end
|
|
128
128
|
|
|
129
129
|
it 'does not modify the parameters' do
|
|
@@ -314,7 +314,11 @@ module Ransack
|
|
|
314
314
|
end
|
|
315
315
|
|
|
316
316
|
it 'should function correctly with a multi-parameter attribute' do
|
|
317
|
-
::ActiveRecord::
|
|
317
|
+
if ::ActiveRecord::VERSION::MAJOR >= 7
|
|
318
|
+
::ActiveRecord.default_timezone = :utc
|
|
319
|
+
else
|
|
320
|
+
::ActiveRecord::Base.default_timezone = :utc
|
|
321
|
+
end
|
|
318
322
|
Time.zone = 'UTC'
|
|
319
323
|
|
|
320
324
|
date = Date.current
|
|
@@ -690,6 +694,10 @@ module Ransack
|
|
|
690
694
|
it { should eq [] }
|
|
691
695
|
end
|
|
692
696
|
|
|
697
|
+
private
|
|
698
|
+
def rails7_and_mysql
|
|
699
|
+
::ActiveRecord::VERSION::MAJOR >= 7 && ENV['DB'] == 'mysql'
|
|
700
|
+
end
|
|
693
701
|
end
|
|
694
702
|
end
|
|
695
703
|
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 '▲'
|
|
@@ -3,6 +3,19 @@ require 'spec_helper'
|
|
|
3
3
|
module Ransack
|
|
4
4
|
module Nodes
|
|
5
5
|
describe Condition do
|
|
6
|
+
context 'bug report #1245' do
|
|
7
|
+
it 'preserves tuple behavior' do
|
|
8
|
+
ransack_hash = {
|
|
9
|
+
m: 'and',
|
|
10
|
+
g: [
|
|
11
|
+
{ title_type_in: ['["title 1", ""]'] }
|
|
12
|
+
]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
sql = Article.ransack(ransack_hash).result.to_sql
|
|
16
|
+
expect(sql).to include("IN (('title 1', ''))")
|
|
17
|
+
end
|
|
18
|
+
end
|
|
6
19
|
|
|
7
20
|
context 'with an alias' do
|
|
8
21
|
subject {
|
data/spec/ransack/search_spec.rb
CHANGED
|
@@ -20,10 +20,42 @@ module Ransack
|
|
|
20
20
|
Search.new(Person, name_eq: 'foobar')
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
context 'whitespace stripping' do
|
|
24
|
+
context 'when whitespace_strip option is true' do
|
|
25
|
+
before do
|
|
26
|
+
Ransack.configure { |c| c.strip_whitespace = true }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'strips leading & trailing whitespace before building' do
|
|
30
|
+
expect_any_instance_of(Search).to receive(:build)
|
|
31
|
+
.with({ 'name_eq' => 'foobar' })
|
|
32
|
+
Search.new(Person, name_eq: ' foobar ')
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
context 'when whitespace_strip option is false' do
|
|
37
|
+
before do
|
|
38
|
+
Ransack.configure { |c| c.strip_whitespace = false }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'doesn\'t strip leading & trailing whitespace before building' do
|
|
42
|
+
expect_any_instance_of(Search).to receive(:build)
|
|
43
|
+
.with({ 'name_eq' => ' foobar ' })
|
|
44
|
+
Search.new(Person, name_eq: ' foobar ')
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'strips leading & trailing whitespace when strip_whitespace search parameter is true' do
|
|
49
|
+
expect_any_instance_of(Search).to receive(:build)
|
|
50
|
+
.with({ 'name_eq' => 'foobar' })
|
|
51
|
+
Search.new(Person, { name_eq: ' foobar ' }, { strip_whitespace: true })
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it 'doesn\'t strip leading & trailing whitespace when strip_whitespace search parameter is false' do
|
|
55
|
+
expect_any_instance_of(Search).to receive(:build)
|
|
56
|
+
.with({ 'name_eq' => ' foobar ' })
|
|
57
|
+
Search.new(Person, { name_eq: ' foobar ' }, { strip_whitespace: false })
|
|
58
|
+
end
|
|
27
59
|
end
|
|
28
60
|
|
|
29
61
|
it 'removes empty suffixed conditions before building' do
|
|
@@ -300,8 +332,6 @@ module Ransack
|
|
|
300
332
|
end
|
|
301
333
|
|
|
302
334
|
it 'use appropriate table alias' do
|
|
303
|
-
skip "Rails 6 regressed here, but it's fixed in 6-0-stable since https://github.com/rails/rails/commit/f9ba52477ca288e7effa5f6794ae3df3f4e982bc" if ENV["RAILS"] == "v6.0.3"
|
|
304
|
-
|
|
305
335
|
s = Search.new(Person, {
|
|
306
336
|
name_eq: "person_name_query",
|
|
307
337
|
articles_title_eq: "person_article_title_query",
|
|
@@ -451,82 +481,109 @@ module Ransack
|
|
|
451
481
|
expect(sort.dir).to eq 'asc'
|
|
452
482
|
end
|
|
453
483
|
|
|
454
|
-
it 'creates sorts based on
|
|
455
|
-
@s.sorts =
|
|
484
|
+
it 'creates sorts based on a single alias/direction' do
|
|
485
|
+
@s.sorts = 'daddy desc'
|
|
486
|
+
expect(@s.sorts.size).to eq(1)
|
|
487
|
+
sort = @s.sorts.first
|
|
488
|
+
expect(sort).to be_a Nodes::Sort
|
|
489
|
+
expect(sort.name).to eq 'parent_name'
|
|
490
|
+
expect(sort.dir).to eq 'desc'
|
|
491
|
+
end
|
|
492
|
+
|
|
493
|
+
it 'creates sorts based on a single alias and uppercase direction' do
|
|
494
|
+
@s.sorts = 'daddy DESC'
|
|
495
|
+
expect(@s.sorts.size).to eq(1)
|
|
496
|
+
sort = @s.sorts.first
|
|
497
|
+
expect(sort).to be_a Nodes::Sort
|
|
498
|
+
expect(sort.name).to eq 'parent_name'
|
|
499
|
+
expect(sort.dir).to eq 'desc'
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
it 'creates sorts based on a single alias and without direction' do
|
|
503
|
+
@s.sorts = 'daddy'
|
|
504
|
+
expect(@s.sorts.size).to eq(1)
|
|
505
|
+
sort = @s.sorts.first
|
|
506
|
+
expect(sort).to be_a Nodes::Sort
|
|
507
|
+
expect(sort.name).to eq 'parent_name'
|
|
508
|
+
expect(sort.dir).to eq 'asc'
|
|
509
|
+
end
|
|
510
|
+
|
|
511
|
+
it 'creates sorts based on attributes, alias and directions in array format' do
|
|
512
|
+
@s.sorts = ['id desc', { name: 'daddy', dir: 'asc' }]
|
|
456
513
|
expect(@s.sorts.size).to eq(2)
|
|
457
514
|
sort1, sort2 = @s.sorts
|
|
458
515
|
expect(sort1).to be_a Nodes::Sort
|
|
459
516
|
expect(sort1.name).to eq 'id'
|
|
460
517
|
expect(sort1.dir).to eq 'desc'
|
|
461
518
|
expect(sort2).to be_a Nodes::Sort
|
|
462
|
-
expect(sort2.name).to eq '
|
|
519
|
+
expect(sort2.name).to eq 'parent_name'
|
|
463
520
|
expect(sort2.dir).to eq 'asc'
|
|
464
521
|
end
|
|
465
522
|
|
|
466
|
-
it 'creates sorts based on
|
|
467
|
-
@s.sorts = ['id DESC', { name: '
|
|
523
|
+
it 'creates sorts based on attributes, alias and uppercase directions in array format' do
|
|
524
|
+
@s.sorts = ['id DESC', { name: 'daddy', dir: 'ASC' }]
|
|
468
525
|
expect(@s.sorts.size).to eq(2)
|
|
469
526
|
sort1, sort2 = @s.sorts
|
|
470
527
|
expect(sort1).to be_a Nodes::Sort
|
|
471
528
|
expect(sort1.name).to eq 'id'
|
|
472
529
|
expect(sort1.dir).to eq 'desc'
|
|
473
530
|
expect(sort2).to be_a Nodes::Sort
|
|
474
|
-
expect(sort2.name).to eq '
|
|
531
|
+
expect(sort2.name).to eq 'parent_name'
|
|
475
532
|
expect(sort2.dir).to eq 'asc'
|
|
476
533
|
end
|
|
477
534
|
|
|
478
|
-
it 'creates sorts based on
|
|
535
|
+
it 'creates sorts based on attributes, alias and different directions
|
|
479
536
|
in array format' do
|
|
480
|
-
@s.sorts = ['id DESC', { name: '
|
|
537
|
+
@s.sorts = ['id DESC', { name: 'daddy', dir: nil }]
|
|
481
538
|
expect(@s.sorts.size).to eq(2)
|
|
482
539
|
sort1, sort2 = @s.sorts
|
|
483
540
|
expect(sort1).to be_a Nodes::Sort
|
|
484
541
|
expect(sort1.name).to eq 'id'
|
|
485
542
|
expect(sort1.dir).to eq 'desc'
|
|
486
543
|
expect(sort2).to be_a Nodes::Sort
|
|
487
|
-
expect(sort2.name).to eq '
|
|
544
|
+
expect(sort2.name).to eq 'parent_name'
|
|
488
545
|
expect(sort2.dir).to eq 'asc'
|
|
489
546
|
end
|
|
490
547
|
|
|
491
|
-
it 'creates sorts based on
|
|
548
|
+
it 'creates sorts based on attributes, alias and directions in hash format' do
|
|
492
549
|
@s.sorts = {
|
|
493
550
|
'0' => { name: 'id', dir: 'desc' },
|
|
494
|
-
'1' => { name: '
|
|
551
|
+
'1' => { name: 'daddy', dir: 'asc' }
|
|
495
552
|
}
|
|
496
553
|
expect(@s.sorts.size).to eq(2)
|
|
497
554
|
expect(@s.sorts).to be_all { |s| Nodes::Sort === s }
|
|
498
555
|
id_sort = @s.sorts.detect { |s| s.name == 'id' }
|
|
499
|
-
|
|
556
|
+
daddy_sort = @s.sorts.detect { |s| s.name == 'parent_name' }
|
|
500
557
|
expect(id_sort.dir).to eq 'desc'
|
|
501
|
-
expect(
|
|
558
|
+
expect(daddy_sort.dir).to eq 'asc'
|
|
502
559
|
end
|
|
503
560
|
|
|
504
|
-
it 'creates sorts based on
|
|
561
|
+
it 'creates sorts based on attributes, alias and uppercase directions
|
|
505
562
|
in hash format' do
|
|
506
563
|
@s.sorts = {
|
|
507
564
|
'0' => { name: 'id', dir: 'DESC' },
|
|
508
|
-
'1' => { name: '
|
|
565
|
+
'1' => { name: 'daddy', dir: 'ASC' }
|
|
509
566
|
}
|
|
510
567
|
expect(@s.sorts.size).to eq(2)
|
|
511
568
|
expect(@s.sorts).to be_all { |s| Nodes::Sort === s }
|
|
512
569
|
id_sort = @s.sorts.detect { |s| s.name == 'id' }
|
|
513
|
-
|
|
570
|
+
daddy_sort = @s.sorts.detect { |s| s.name == 'parent_name' }
|
|
514
571
|
expect(id_sort.dir).to eq 'desc'
|
|
515
|
-
expect(
|
|
572
|
+
expect(daddy_sort.dir).to eq 'asc'
|
|
516
573
|
end
|
|
517
574
|
|
|
518
|
-
it 'creates sorts based on
|
|
575
|
+
it 'creates sorts based on attributes, alias and different directions
|
|
519
576
|
in hash format' do
|
|
520
577
|
@s.sorts = {
|
|
521
578
|
'0' => { name: 'id', dir: 'DESC' },
|
|
522
|
-
'1' => { name: '
|
|
579
|
+
'1' => { name: 'daddy', dir: nil }
|
|
523
580
|
}
|
|
524
581
|
expect(@s.sorts.size).to eq(2)
|
|
525
582
|
expect(@s.sorts).to be_all { |s| Nodes::Sort === s }
|
|
526
583
|
id_sort = @s.sorts.detect { |s| s.name == 'id' }
|
|
527
|
-
|
|
584
|
+
daddy_sort = @s.sorts.detect { |s| s.name == 'parent_name' }
|
|
528
585
|
expect(id_sort.dir).to eq 'desc'
|
|
529
|
-
expect(
|
|
586
|
+
expect(daddy_sort.dir).to eq 'asc'
|
|
530
587
|
end
|
|
531
588
|
|
|
532
589
|
it 'overrides existing sort' do
|
|
@@ -554,6 +611,39 @@ module Ransack
|
|
|
554
611
|
|
|
555
612
|
Ransack.options = default
|
|
556
613
|
end
|
|
614
|
+
|
|
615
|
+
it "PG's sort option with double name", if: ::ActiveRecord::Base.connection.adapter_name == "PostgreSQL" do
|
|
616
|
+
default = Ransack.options.clone
|
|
617
|
+
|
|
618
|
+
s = Search.new(Person, s: 'doubled_name asc')
|
|
619
|
+
expect(s.result.to_sql).to eq "SELECT \"people\".* FROM \"people\" ORDER BY \"people\".\"name\" || \"people\".\"name\" ASC"
|
|
620
|
+
|
|
621
|
+
Ransack.configure { |c| c.postgres_fields_sort_option = :nulls_first }
|
|
622
|
+
s = Search.new(Person, s: 'doubled_name asc')
|
|
623
|
+
expect(s.result.to_sql).to eq "SELECT \"people\".* FROM \"people\" ORDER BY \"people\".\"name\" || \"people\".\"name\" ASC NULLS FIRST"
|
|
624
|
+
s = Search.new(Person, s: 'doubled_name desc')
|
|
625
|
+
expect(s.result.to_sql).to eq "SELECT \"people\".* FROM \"people\" ORDER BY \"people\".\"name\" || \"people\".\"name\" DESC NULLS LAST"
|
|
626
|
+
|
|
627
|
+
Ransack.configure { |c| c.postgres_fields_sort_option = :nulls_last }
|
|
628
|
+
s = Search.new(Person, s: 'doubled_name asc')
|
|
629
|
+
expect(s.result.to_sql).to eq "SELECT \"people\".* FROM \"people\" ORDER BY \"people\".\"name\" || \"people\".\"name\" ASC NULLS LAST"
|
|
630
|
+
s = Search.new(Person, s: 'doubled_name desc')
|
|
631
|
+
expect(s.result.to_sql).to eq "SELECT \"people\".* FROM \"people\" ORDER BY \"people\".\"name\" || \"people\".\"name\" DESC NULLS FIRST"
|
|
632
|
+
|
|
633
|
+
Ransack.configure { |c| c.postgres_fields_sort_option = :nulls_always_first }
|
|
634
|
+
s = Search.new(Person, s: 'doubled_name asc')
|
|
635
|
+
expect(s.result.to_sql).to eq "SELECT \"people\".* FROM \"people\" ORDER BY \"people\".\"name\" || \"people\".\"name\" ASC NULLS FIRST"
|
|
636
|
+
s = Search.new(Person, s: 'doubled_name desc')
|
|
637
|
+
expect(s.result.to_sql).to eq "SELECT \"people\".* FROM \"people\" ORDER BY \"people\".\"name\" || \"people\".\"name\" DESC NULLS FIRST"
|
|
638
|
+
|
|
639
|
+
Ransack.configure { |c| c.postgres_fields_sort_option = :nulls_always_last }
|
|
640
|
+
s = Search.new(Person, s: 'doubled_name asc')
|
|
641
|
+
expect(s.result.to_sql).to eq "SELECT \"people\".* FROM \"people\" ORDER BY \"people\".\"name\" || \"people\".\"name\" ASC NULLS LAST"
|
|
642
|
+
s = Search.new(Person, s: 'doubled_name desc')
|
|
643
|
+
expect(s.result.to_sql).to eq "SELECT \"people\".* FROM \"people\" ORDER BY \"people\".\"name\" || \"people\".\"name\" DESC NULLS LAST"
|
|
644
|
+
|
|
645
|
+
Ransack.options = default
|
|
646
|
+
end
|
|
557
647
|
end
|
|
558
648
|
|
|
559
649
|
describe '#method_missing' do
|
data/spec/support/schema.rb
CHANGED
|
@@ -138,6 +138,29 @@ class Article < ActiveRecord::Base
|
|
|
138
138
|
alias_attribute :content, :body
|
|
139
139
|
|
|
140
140
|
default_scope { where("'default_scope' = 'default_scope'") }
|
|
141
|
+
|
|
142
|
+
ransacker :title_type, formatter: lambda { |tuples|
|
|
143
|
+
title, type = JSON.parse(tuples)
|
|
144
|
+
Arel::Nodes::Grouping.new(
|
|
145
|
+
[
|
|
146
|
+
Arel::Nodes.build_quoted(title),
|
|
147
|
+
Arel::Nodes.build_quoted(type)
|
|
148
|
+
]
|
|
149
|
+
)
|
|
150
|
+
} do |_parent|
|
|
151
|
+
articles = Article.arel_table
|
|
152
|
+
Arel::Nodes::Grouping.new(
|
|
153
|
+
%i[title type].map do |field|
|
|
154
|
+
Arel::Nodes::NamedFunction.new(
|
|
155
|
+
'COALESCE',
|
|
156
|
+
[
|
|
157
|
+
Arel::Nodes::NamedFunction.new('TRIM', [articles[field]]),
|
|
158
|
+
Arel::Nodes.build_quoted('')
|
|
159
|
+
]
|
|
160
|
+
)
|
|
161
|
+
end
|
|
162
|
+
)
|
|
163
|
+
end
|
|
141
164
|
end
|
|
142
165
|
|
|
143
166
|
class StoryArticle < Article
|
metadata
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ransack
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ernie Miller
|
|
8
8
|
- Ryan Bigg
|
|
9
9
|
- Jon Atack
|
|
10
10
|
- Sean Carroll
|
|
11
|
-
autorequire:
|
|
11
|
+
autorequire:
|
|
12
12
|
bindir: bin
|
|
13
13
|
cert_chain: []
|
|
14
|
-
date: 2021-
|
|
14
|
+
date: 2021-12-25 00:00:00.000000000 Z
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
17
17
|
name: activerecord
|
|
@@ -83,6 +83,7 @@ files:
|
|
|
83
83
|
- bug_report_templates/test-ransacker-arel-present-predicate.rb
|
|
84
84
|
- docs/img/create_release.png
|
|
85
85
|
- docs/release_process.md
|
|
86
|
+
- lib/polyamorous.rb
|
|
86
87
|
- lib/polyamorous/activerecord_5.2_ruby_2/join_association.rb
|
|
87
88
|
- lib/polyamorous/activerecord_5.2_ruby_2/join_dependency.rb
|
|
88
89
|
- lib/polyamorous/activerecord_5.2_ruby_2/reflection.rb
|
|
@@ -92,9 +93,9 @@ files:
|
|
|
92
93
|
- lib/polyamorous/activerecord_6.1_ruby_2/join_association.rb
|
|
93
94
|
- lib/polyamorous/activerecord_6.1_ruby_2/join_dependency.rb
|
|
94
95
|
- lib/polyamorous/activerecord_6.1_ruby_2/reflection.rb
|
|
95
|
-
- lib/polyamorous/
|
|
96
|
-
- lib/polyamorous/
|
|
97
|
-
- lib/polyamorous/
|
|
96
|
+
- lib/polyamorous/activerecord_7.0_ruby_2/join_association.rb
|
|
97
|
+
- lib/polyamorous/activerecord_7.0_ruby_2/join_dependency.rb
|
|
98
|
+
- lib/polyamorous/activerecord_7.0_ruby_2/reflection.rb
|
|
98
99
|
- lib/polyamorous/join.rb
|
|
99
100
|
- lib/polyamorous/polyamorous.rb
|
|
100
101
|
- lib/polyamorous/swapping_reflection_class.rb
|
|
@@ -137,6 +138,7 @@ files:
|
|
|
137
138
|
- lib/ransack/locale/ro.yml
|
|
138
139
|
- lib/ransack/locale/ru.yml
|
|
139
140
|
- lib/ransack/locale/sk.yml
|
|
141
|
+
- lib/ransack/locale/sv.yml
|
|
140
142
|
- lib/ransack/locale/tr.yml
|
|
141
143
|
- lib/ransack/locale/zh-CN.yml
|
|
142
144
|
- lib/ransack/locale/zh-TW.yml
|
|
@@ -190,7 +192,7 @@ homepage: https://github.com/activerecord-hackery/ransack
|
|
|
190
192
|
licenses:
|
|
191
193
|
- MIT
|
|
192
194
|
metadata: {}
|
|
193
|
-
post_install_message:
|
|
195
|
+
post_install_message:
|
|
194
196
|
rdoc_options: []
|
|
195
197
|
require_paths:
|
|
196
198
|
- lib
|
|
@@ -205,8 +207,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
205
207
|
- !ruby/object:Gem::Version
|
|
206
208
|
version: '0'
|
|
207
209
|
requirements: []
|
|
208
|
-
rubygems_version: 3.
|
|
209
|
-
signing_key:
|
|
210
|
+
rubygems_version: 3.1.4
|
|
211
|
+
signing_key:
|
|
210
212
|
specification_version: 4
|
|
211
213
|
summary: Object-based searching for Active Record and Mongoid (currently).
|
|
212
214
|
test_files:
|