ransack 1.8.2 → 1.8.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +14 -15
- data/CHANGELOG.md +43 -0
- data/README.md +89 -39
- data/lib/ransack.rb +0 -7
- data/lib/ransack/adapters/active_record.rb +11 -1
- data/lib/ransack/adapters/active_record/base.rb +2 -1
- data/lib/ransack/adapters/active_record/ransack/nodes/condition.rb +7 -2
- data/lib/ransack/adapters/mongoid.rb +2 -0
- data/lib/ransack/adapters/mongoid/base.rb +6 -17
- data/lib/ransack/configuration.rb +41 -1
- data/lib/ransack/helpers/form_helper.rb +2 -2
- data/lib/ransack/search.rb +8 -2
- data/lib/ransack/version.rb +1 -1
- data/spec/mongoid/adapters/mongoid/base_spec.rb +21 -2
- data/spec/mongoid/configuration_spec.rb +71 -11
- data/spec/mongoid/search_spec.rb +0 -1
- data/spec/mongoid/support/schema.rb +3 -0
- data/spec/ransack/adapters/active_record/base_spec.rb +41 -14
- data/spec/ransack/configuration_spec.rb +72 -14
- data/spec/ransack/helpers/form_helper_spec.rb +104 -2
- data/spec/ransack/predicate_spec.rb +22 -0
- data/spec/support/schema.rb +3 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d068e0ef0efe6ce1a4afdb11cc36361f94bbcf68
|
4
|
+
data.tar.gz: 2ab905dd3037f405cfc262e2440cbfa557c5a799
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 354a8a5fc605f5efb7da6d1b78544f93780293418ac9a4578ae395fb608dbd69d301d5a129fbc6cf20c46427427fbeba04b0f7ea040b54771aaecbd31cf174ac
|
7
|
+
data.tar.gz: 388a7b733a5460acd980703c6d918077fc27e4777f8acf0b2f3c72b696664c1ef9997c477de74a772ea776eb56521d65cda03bb7f190441575801a4d65b479d6
|
data/.travis.yml
CHANGED
@@ -3,11 +3,10 @@ language: ruby
|
|
3
3
|
sudo: false
|
4
4
|
|
5
5
|
rvm:
|
6
|
-
- 2.3.
|
7
|
-
- 2.2.
|
6
|
+
- 2.3.3
|
7
|
+
- 2.2.6
|
8
8
|
- 2.1.10
|
9
9
|
- 2.0
|
10
|
-
- 1.9
|
11
10
|
|
12
11
|
env:
|
13
12
|
- RAILS=5-0-stable DB=sqlite3
|
@@ -50,26 +49,26 @@ matrix:
|
|
50
49
|
- rvm: 2.0
|
51
50
|
env: RAILS=5-0-stable DB=postgres
|
52
51
|
|
53
|
-
- rvm:
|
54
|
-
env: RAILS=
|
55
|
-
- rvm:
|
56
|
-
env: RAILS=
|
57
|
-
- rvm:
|
58
|
-
env: RAILS=
|
52
|
+
- rvm: 2.0
|
53
|
+
env: RAILS=4-2-stable DB=sqlite3
|
54
|
+
- rvm: 2.0
|
55
|
+
env: RAILS=4-2-stable DB=mysql
|
56
|
+
- rvm: 2.0
|
57
|
+
env: RAILS=4-2-stable DB=postgres
|
59
58
|
|
60
59
|
include:
|
61
|
-
- rvm: 2.3.
|
60
|
+
- rvm: 2.3.3
|
62
61
|
env: RAILS=master DB=sqlite3
|
63
|
-
- rvm: 2.3.
|
62
|
+
- rvm: 2.3.3
|
64
63
|
env: RAILS=master DB=mysql
|
65
|
-
- rvm: 2.3.
|
64
|
+
- rvm: 2.3.3
|
66
65
|
env: RAILS=master DB=postgres
|
67
66
|
|
68
|
-
- rvm: 2.2.
|
67
|
+
- rvm: 2.2.6
|
69
68
|
env: RAILS=master DB=sqlite3
|
70
|
-
- rvm: 2.2.
|
69
|
+
- rvm: 2.2.6
|
71
70
|
env: RAILS=master DB=mysql
|
72
|
-
- rvm: 2.2.
|
71
|
+
- rvm: 2.2.6
|
73
72
|
env: RAILS=master DB=postgres
|
74
73
|
|
75
74
|
allow_failures:
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,48 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## Unreleased
|
4
|
+
|
5
|
+
### Added
|
6
|
+
|
7
|
+
* Add a config option to customize the up and down arrows used for direction
|
8
|
+
indicators in Ransack sort links.
|
9
|
+
PR [#726](https://github.com/activerecord-hackery/ransack/pull/726).
|
10
|
+
|
11
|
+
*Garett Arrowood*
|
12
|
+
|
13
|
+
* Add ability to turn off sanitization of custom scope arguments.
|
14
|
+
PR [#742](https://github.com/activerecord-hackery/ransack/pull/742).
|
15
|
+
|
16
|
+
*Garett Arrowood*
|
17
|
+
|
18
|
+
### Fixed
|
19
|
+
|
20
|
+
* Use class attributes properly so that inheritance is respected.
|
21
|
+
PR [#717](https://github.com/activerecord-hackery/ransack/pull/717).
|
22
|
+
This fixes two bugs:
|
23
|
+
|
24
|
+
1. In the Mongoid adapter, subclasses were not properly inheriting their
|
25
|
+
parents' Ransack aliases because each class defined its own set of
|
26
|
+
aliases.
|
27
|
+
|
28
|
+
2. In the Active Record adapter, Ransack aliases were defined in such a way
|
29
|
+
that the parent's (and grandparent's, etc.) aliases were overwritten by
|
30
|
+
the child, meaning that all aliases were ultimately kept on
|
31
|
+
`ActiveRecord::Base`. This had the unfortunate effect of enforcing
|
32
|
+
uniqueness of Ransack alias names across all models rather than per
|
33
|
+
model. Depending on the load order of models, earlier definitions of an
|
34
|
+
alias in other models were clobbered.
|
35
|
+
|
36
|
+
*Steve Richert (laserlemon)*
|
37
|
+
|
38
|
+
* Use `ActiveSupport.on_load` hooks to include Ransack in Active Record,
|
39
|
+
avoiding autoloading the constant too soon. PR
|
40
|
+
[#719](https://github.com/activerecord-hackery/ransack/pull/719). Reference:
|
41
|
+
[This comment in rails#23589]
|
42
|
+
(https://github.com/rails/rails/issues/23589#issuecomment-229247727).
|
43
|
+
|
44
|
+
*Yuji Yaginuma (y-yagi)*
|
45
|
+
|
3
46
|
## Version 1.8.2 - 2016-08-08
|
4
47
|
### Fixed
|
5
48
|
|
data/README.md
CHANGED
@@ -7,20 +7,21 @@
|
|
7
7
|
[![Code Climate](https://codeclimate.com/github/activerecord-hackery/ransack/badges/gpa.svg)]
|
8
8
|
(https://codeclimate.com/github/activerecord-hackery/ransack)
|
9
9
|
|
10
|
-
Ransack is a rewrite of [MetaSearch]
|
11
|
-
(https://github.com/activerecord-hackery/meta_search)
|
10
|
+
Ransack is a rewrite of [MetaSearch](https://github.com/activerecord-hackery/meta_search)
|
12
11
|
created by [Ernie Miller](http://twitter.com/erniemiller)
|
13
|
-
and maintained
|
14
|
-
[Jon Atack](http://twitter.com/jonatack) and
|
15
|
-
(
|
12
|
+
and developed/maintained for years by
|
13
|
+
[Jon Atack](http://twitter.com/jonatack) and
|
14
|
+
[Ryan Bigg](http://twitter.com/ryanbigg) with the help of a great group of
|
15
|
+
[contributors](https://github.com/activerecord-hackery/ransack/graphs/contributors).
|
16
16
|
While it supports many of the same features as MetaSearch, its underlying
|
17
17
|
implementation differs greatly from MetaSearch,
|
18
18
|
and backwards compatibility is not a design goal.
|
19
19
|
|
20
|
-
Ransack enables the creation of both
|
21
|
-
[
|
22
|
-
|
23
|
-
|
20
|
+
Ransack enables the creation of both
|
21
|
+
[simple](http://ransack-demo.herokuapp.com) and
|
22
|
+
[advanced](http://ransack-demo.herokuapp.com/users/advanced_search) search forms
|
23
|
+
for your Ruby on Rails application
|
24
|
+
([demo source code here](https://github.com/activerecord-hackery/ransack_demo)).
|
24
25
|
If you're looking for something that simplifies query generation at the model
|
25
26
|
or controller layer, you're probably not looking for Ransack (or MetaSearch,
|
26
27
|
for that matter). Try [Squeel](https://github.com/activerecord-hackery/squeel)
|
@@ -56,11 +57,6 @@ branch:
|
|
56
57
|
gem 'ransack', github: 'activerecord-hackery/ransack'
|
57
58
|
```
|
58
59
|
|
59
|
-
If you are using Rails 5 or master and need pagination compatible with it and
|
60
|
-
Ransack, there is a [Rails 5 version of the `will_paginate` gem here](https://github.com/jonatack/will_paginate).
|
61
|
-
It is also optimized for Ruby 2.2+. To use it, in your Gemfile:
|
62
|
-
`gem 'will_paginate', github: 'jonatack/will_paginate'`.
|
63
|
-
|
64
60
|
## Issues tracker
|
65
61
|
|
66
62
|
* Before filing an issue, please read the [Contributing Guide](CONTRIBUTING.md).
|
@@ -82,8 +78,7 @@ If you're coming from MetaSearch, things to note:
|
|
82
78
|
1. The default param key for search params is now `:q`, instead of `:search`.
|
83
79
|
This is primarily to shorten query strings, though advanced queries (below)
|
84
80
|
will still run afoul of URL length limits in most browsers and require a
|
85
|
-
switch to HTTP POST requests. This key is [configurable]
|
86
|
-
(https://github.com/activerecord-hackery/ransack/wiki/Configuration).
|
81
|
+
switch to HTTP POST requests. This key is [configurable](https://github.com/activerecord-hackery/ransack/wiki/Configuration).
|
87
82
|
|
88
83
|
2. `form_for` is now `search_form_for`, and validates that a Ransack::Search
|
89
84
|
object is passed to it.
|
@@ -93,7 +88,7 @@ If you're coming from MetaSearch, things to note:
|
|
93
88
|
ActiveRecord::Relation in the case of the ActiveRecord adapter) via a call to
|
94
89
|
`Ransack#result`.
|
95
90
|
|
96
|
-
####In your controller
|
91
|
+
#### In your controller
|
97
92
|
|
98
93
|
```ruby
|
99
94
|
def index
|
@@ -114,13 +109,13 @@ def index
|
|
114
109
|
end
|
115
110
|
```
|
116
111
|
|
117
|
-
####In your view
|
112
|
+
#### In your view
|
118
113
|
|
119
114
|
The two primary Ransack view helpers are `search_form_for` and `sort_link`,
|
120
115
|
which are defined in
|
121
116
|
[Ransack::Helpers::FormHelper](lib/ransack/helpers/form_helper.rb).
|
122
117
|
|
123
|
-
####Ransack's `search_form_for` helper replaces `form_for` for creating the view search form
|
118
|
+
#### Ransack's `search_form_for` helper replaces `form_for` for creating the view search form
|
124
119
|
|
125
120
|
```erb
|
126
121
|
<%= search_form_for @q do |f| %>
|
@@ -156,7 +151,7 @@ The `search_form_for` answer format can be set like this:
|
|
156
151
|
<%= search_form_for(@q, format: :json) do |f| %>
|
157
152
|
```
|
158
153
|
|
159
|
-
####Ransack's `sort_link` helper creates table headers that are sortable links
|
154
|
+
#### Ransack's `sort_link` helper creates table headers that are sortable links
|
160
155
|
|
161
156
|
```erb
|
162
157
|
<%= sort_link(@q, :name) %>
|
@@ -205,15 +200,23 @@ This example toggles the sort directions of both fields, by default
|
|
205
200
|
initially sorting the `last_name` field by ascending order, and the
|
206
201
|
`first_name` field by descending order.
|
207
202
|
|
208
|
-
The sort link may be displayed without the order indicator arrow by passing
|
209
|
-
`hide_indicator: true`:
|
210
203
|
|
211
|
-
|
212
|
-
|
204
|
+
The sort link order indicator arrows may be globally customized by setting a
|
205
|
+
`custom_arrows` option in an initializer file like
|
206
|
+
`config/initializers/ransack.rb`:
|
207
|
+
|
208
|
+
```ruby
|
209
|
+
Ransack.configure do |c|
|
210
|
+
c.custom_arrows = {
|
211
|
+
up_arrow: '<i class="custom-up-arrow-icon"></i>',
|
212
|
+
down_arrow: 'U+02193'
|
213
|
+
}
|
214
|
+
end
|
213
215
|
```
|
214
216
|
|
215
|
-
|
216
|
-
by
|
217
|
+
All sort links may be displayed without the order indicator
|
218
|
+
arrows by setting `hide_sort_order_indicators` to true in the initializer file.
|
219
|
+
Note that this hides the arrows even if they were customized:
|
217
220
|
|
218
221
|
```ruby
|
219
222
|
Ransack.configure do |c|
|
@@ -221,7 +224,14 @@ Ransack.configure do |c|
|
|
221
224
|
end
|
222
225
|
```
|
223
226
|
|
224
|
-
|
227
|
+
Without setting it globally, individual sort links may be displayed without
|
228
|
+
the order indicator arrow by passing `hide_indicator: true` in the sort link:
|
229
|
+
|
230
|
+
```erb
|
231
|
+
<%= sort_link(@q, :name, hide_indicator: true) %>
|
232
|
+
```
|
233
|
+
|
234
|
+
#### Ransack's `sort_url` helper is like a `sort_link` but returns only the url
|
225
235
|
|
226
236
|
`sort_url` has the same API as `sort_link`:
|
227
237
|
|
@@ -275,11 +285,12 @@ end
|
|
275
285
|
|
276
286
|
Once you've done so, you can make use of the helpers in [Ransack::Helpers::FormBuilder](lib/ransack/helpers/form_builder.rb) to
|
277
287
|
construct much more complex search forms, such as the one on the
|
278
|
-
[demo
|
288
|
+
[demo app](http://ransack-demo.herokuapp.com/users/advanced_search)
|
289
|
+
(source code [here](https://github.com/activerecord-hackery/ransack_demo)).
|
279
290
|
|
280
291
|
### Ransack #search method
|
281
292
|
|
282
|
-
Ransack will try to
|
293
|
+
Ransack will try to make the class method `#search` available in your
|
283
294
|
models, but if `#search` has already been defined elsewhere, you can always use
|
284
295
|
the default `#ransack` class method. So the following are equivalent:
|
285
296
|
|
@@ -395,13 +406,41 @@ query parameters in your URLs.
|
|
395
406
|
<% end %>
|
396
407
|
```
|
397
408
|
|
409
|
+
### Search Matchers
|
410
|
+
|
411
|
+
List of all possible predicates
|
412
|
+
|
413
|
+
* `*_eq` - equal
|
414
|
+
* `*_not_eq` - not equal
|
415
|
+
* `*_matches` - matches with `LIKE`, e.g. `q[email_matches]=%@gmail.com`
|
416
|
+
* Also: `*_does_not_match`, `*_matches_any`, `*_matches_all`, `*_does_not_match_any`, `*_does_not_match_all`
|
417
|
+
* `*_lt` - less than
|
418
|
+
* `*_lteq` - less than or equal
|
419
|
+
* `*_gt` - greater than
|
420
|
+
* `*_gteq` - greater than or equal
|
421
|
+
* `*_present` - not null and not empty, e.g. `q[name_present]=1` (SQL: `col is not null AND col != ''`)
|
422
|
+
* `*_blank` - is null or empty. (SQL: `col is null OR col = ''`)
|
423
|
+
* `*_null`, `*_not_null` - is null, is not null
|
424
|
+
* `*_in` - match any values in array, e.g. `q[name_in][]=Alice&q[name_in][]=Bob`
|
425
|
+
* `*_not_in` - match none of values in array
|
426
|
+
* `*_lt_any`, `*_lteq_any`, `*_gt_any`, `*_gteq_any` - Compare to list of values, at least positive. (SQL: `col > value1 OR col > value2`)
|
427
|
+
* `*_matches_any`, `*_does_not_match_any` - same as above but with `LIKE`
|
428
|
+
* `*_lt_all`, `*_lteq_all`, `*_gt_all`, `*_gteq_all` - Compare to list of values, all positive. (SQL: `col > value1 AND col > value2`)
|
429
|
+
* `*_matches_all`, `*_does_not_match_all` - same as above but with `LIKE`
|
430
|
+
* `*_not_eq_all` - none of values in a set
|
431
|
+
* `*_start`, `*_not_start`, `*_start_any`, `*_start_all`, `*_not_start_any`, `*_not_start_all` - start with, (SQL: `col LIKE 'value%'`)
|
432
|
+
* `*_end`, `*_not_end`, `*_end_any`, `*_end_all`, `*_not_end_any`, `*_not_end_all` - end with, (SQL: `col LIKE '%value'`)
|
433
|
+
* `*_cont`, `*_cont_any`, `*_cont_all`, `*_not_cont`, `*_not_cont_any`, `*_not_cont_all` - contains value, using `LIKE`
|
434
|
+
* `*_true`, `*_false` - is true and is false
|
435
|
+
|
436
|
+
(See full list: https://github.com/activerecord-hackery/ransack/blob/master/lib/ransack/locale/en.yml#L15 and [wiki](https://github.com/activerecord-hackery/ransack/wiki/Basic-Searching))
|
437
|
+
|
398
438
|
### Using Ransackers to add custom search functions via Arel
|
399
439
|
|
400
440
|
The main premise behind Ransack is to provide access to
|
401
441
|
**Arel predicate methods**. Ransack provides special methods, called
|
402
442
|
_ransackers_, for creating additional search functions via Arel. More
|
403
|
-
information about `ransacker` methods can be found [here in the wiki]
|
404
|
-
(https://github.com/activerecord-hackery/ransack/wiki/Using-Ransackers).
|
443
|
+
information about `ransacker` methods can be found [here in the wiki](https://github.com/activerecord-hackery/ransack/wiki/Using-Ransackers).
|
405
444
|
Feel free to contribute working `ransacker` code examples to the wiki!
|
406
445
|
|
407
446
|
### Problem with DISTINCT selects
|
@@ -511,8 +550,7 @@ for an `auth_object` key in the options hash which can be used by your own
|
|
511
550
|
overridden methods.
|
512
551
|
|
513
552
|
Here is an example that puts all this together, adapted from
|
514
|
-
[this blog post by Ernie Miller]
|
515
|
-
(http://erniemiller.org/2012/05/11/why-your-ruby-class-macros-might-suck-mine-did/).
|
553
|
+
[this blog post by Ernie Miller](http://erniemiller.org/2012/05/11/why-your-ruby-class-macros-might-suck-mine-did/).
|
516
554
|
In an `Article` model, add the following `ransackable_attributes` class method
|
517
555
|
(preferably private):
|
518
556
|
|
@@ -613,7 +651,21 @@ Employee.ransack({ salary_gt: 100_000 }, { auth_object: current_user })
|
|
613
651
|
In Rails 3 and 4, if the `true` value is being passed via url params or some
|
614
652
|
other mechanism that will convert it to a string, the true value may not be
|
615
653
|
passed to the ransackable scope unless you wrap it in an array
|
616
|
-
(i.e. `activated: ['true']`).
|
654
|
+
(i.e. `activated: ['true']`). Ransack will take care of changing 'true' into a
|
655
|
+
boolean. This is currently resolved in Rails 5 :smiley:
|
656
|
+
|
657
|
+
However, perhaps you have `user_id: [1]` and you do not want Ransack to convert
|
658
|
+
1 into a boolean. (Values sanitized to booleans can be found in the
|
659
|
+
[constants.rb](https://github.com/activerecord-hackery/ransack/blob/master/lib/ransack/constants.rb#L28)).
|
660
|
+
To turn this off, and handle type conversions yourself, set
|
661
|
+
`sanitize_custom_scope_booleans` to false in an initializer file like
|
662
|
+
config/initializers/ransack.rb:
|
663
|
+
|
664
|
+
```ruby
|
665
|
+
Ransack.configure do |c|
|
666
|
+
c.sanitize_custom_scope_booleans = false
|
667
|
+
end
|
668
|
+
```
|
617
669
|
|
618
670
|
Scopes are a recent addition to Ransack and currently have a few caveats:
|
619
671
|
First, a scope involving child associations needs to be defined in the parent
|
@@ -622,8 +674,7 @@ argument are not easily usable yet, because the array currently needs to be
|
|
622
674
|
wrapped in an array to function (see
|
623
675
|
[this issue](https://github.com/activerecord-hackery/ransack/issues/404)),
|
624
676
|
which is not compatible with Ransack form helpers. For this use case, it may be
|
625
|
-
better for now to use [ransackers]
|
626
|
-
(https://github.com/activerecord-hackery/ransack/wiki/Using-Ransackers) instead,
|
677
|
+
better for now to use [ransackers](https://github.com/activerecord-hackery/ransack/wiki/Using-Ransackers) instead,
|
627
678
|
where feasible. Pull requests with solutions and tests are welcome!
|
628
679
|
|
629
680
|
### Grouping queries by OR instead of AND
|
@@ -747,9 +798,8 @@ en:
|
|
747
798
|
|
748
799
|
## Mongoid
|
749
800
|
|
750
|
-
Ransack
|
751
|
-
|
752
|
-
[here](http://ransack-mongodb-demo.herokuapp.com/) and the demo source code is
|
801
|
+
Ransack works with Mongoid in the same way as Active Record, except that with
|
802
|
+
Mongoid, associations are not currently supported. Demo source code may be found
|
753
803
|
[here](https://github.com/Zhomart/ransack-mongodb-demo). A `result` method
|
754
804
|
called on a `ransack` search returns a `Mongoid::Criteria` object:
|
755
805
|
|
data/lib/ransack.rb
CHANGED
@@ -7,13 +7,6 @@ Ransack::Adapters.object_mapper.require_constants
|
|
7
7
|
module Ransack
|
8
8
|
extend Configuration
|
9
9
|
class UntraversableAssociationError < StandardError; end;
|
10
|
-
|
11
|
-
SUPPORTS_ATTRIBUTE_ALIAS =
|
12
|
-
begin
|
13
|
-
ActiveRecord::Base.respond_to?(:attribute_aliases)
|
14
|
-
rescue NameError
|
15
|
-
false
|
16
|
-
end
|
17
10
|
end
|
18
11
|
|
19
12
|
Ransack.configure do |config|
|
@@ -1,5 +1,15 @@
|
|
1
1
|
require 'ransack/adapters/active_record/base'
|
2
|
-
|
2
|
+
|
3
|
+
ActiveSupport.on_load(:active_record) do
|
4
|
+
extend Ransack::Adapters::ActiveRecord::Base
|
5
|
+
|
6
|
+
Ransack::SUPPORTS_ATTRIBUTE_ALIAS =
|
7
|
+
begin
|
8
|
+
ActiveRecord::Base.respond_to?(:attribute_aliases)
|
9
|
+
rescue NameError
|
10
|
+
false
|
11
|
+
end
|
12
|
+
end
|
3
13
|
|
4
14
|
require 'ransack/adapters/active_record/context'
|
5
15
|
|
@@ -23,7 +23,8 @@ module Ransack
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def ransack_alias(new_name, old_name)
|
26
|
-
self._ransack_aliases.
|
26
|
+
self._ransack_aliases = _ransack_aliases.merge new_name.to_s =>
|
27
|
+
old_name.to_s
|
27
28
|
end
|
28
29
|
|
29
30
|
# Ransackable_attributes, by default, returns all column names
|
@@ -7,9 +7,14 @@ module Ransack
|
|
7
7
|
association = attribute.parent
|
8
8
|
if negative? && attribute.associated_collection?
|
9
9
|
query = context.build_correlated_subquery(association)
|
10
|
-
query.where(format_predicate(attribute).not)
|
11
10
|
context.remove_association(association)
|
12
|
-
|
11
|
+
if self.predicate_name == 'not_null' && self.value
|
12
|
+
query.where(format_predicate(attribute))
|
13
|
+
Arel::Nodes::In.new(context.primary_key, Arel.sql(query.to_sql))
|
14
|
+
else
|
15
|
+
query.where(format_predicate(attribute).not)
|
16
|
+
Arel::Nodes::NotIn.new(context.primary_key, Arel.sql(query.to_sql))
|
17
|
+
end
|
13
18
|
else
|
14
19
|
format_predicate(attribute)
|
15
20
|
end
|
@@ -8,6 +8,10 @@ module Ransack
|
|
8
8
|
extend ActiveSupport::Concern
|
9
9
|
|
10
10
|
included do
|
11
|
+
class_attribute :_ransackers
|
12
|
+
class_attribute :_ransack_aliases
|
13
|
+
self._ransackers ||= {}
|
14
|
+
self._ransack_aliases ||= {}
|
11
15
|
end
|
12
16
|
|
13
17
|
class ColumnWrapper < SimpleDelegator
|
@@ -33,22 +37,6 @@ module Ransack
|
|
33
37
|
end
|
34
38
|
|
35
39
|
module ClassMethods
|
36
|
-
def _ransack_aliases
|
37
|
-
@_ransack_aliases ||= {}
|
38
|
-
end
|
39
|
-
|
40
|
-
def _ransack_aliases=(value)
|
41
|
-
@_ransack_aliases = value
|
42
|
-
end
|
43
|
-
|
44
|
-
def _ransackers
|
45
|
-
@_ransackers ||= {}
|
46
|
-
end
|
47
|
-
|
48
|
-
def _ransackers=(value)
|
49
|
-
@_ransackers = value
|
50
|
-
end
|
51
|
-
|
52
40
|
def ransack(params = {}, options = {})
|
53
41
|
params = params.presence || {}
|
54
42
|
Search.new(self, params ? params.delete_if {
|
@@ -58,7 +46,8 @@ module Ransack
|
|
58
46
|
alias_method :search, :ransack
|
59
47
|
|
60
48
|
def ransack_alias(new_name, old_name)
|
61
|
-
self._ransack_aliases.
|
49
|
+
self._ransack_aliases = _ransack_aliases.merge new_name.to_s =>
|
50
|
+
old_name.to_s
|
62
51
|
end
|
63
52
|
|
64
53
|
def ransacker(name, opts = {}, &block)
|
@@ -9,7 +9,10 @@ module Ransack
|
|
9
9
|
self.options = {
|
10
10
|
:search_key => :q,
|
11
11
|
:ignore_unknown_conditions => true,
|
12
|
-
:hide_sort_order_indicators => false
|
12
|
+
:hide_sort_order_indicators => false,
|
13
|
+
:up_arrow => '▼'.freeze,
|
14
|
+
:down_arrow => '▲'.freeze,
|
15
|
+
:sanitize_scope_args => true
|
13
16
|
}
|
14
17
|
|
15
18
|
def configure
|
@@ -75,6 +78,43 @@ module Ransack
|
|
75
78
|
self.options[:ignore_unknown_conditions] = boolean
|
76
79
|
end
|
77
80
|
|
81
|
+
# By default, Ransack displays sort order indicator arrows with HTML codes:
|
82
|
+
#
|
83
|
+
# up_arrow: '▼'
|
84
|
+
# down_arrow: '▲'
|
85
|
+
#
|
86
|
+
# One or both defaults may be globally overridden in an initializer file
|
87
|
+
# like `config/initializers/ransack.rb` as follows:
|
88
|
+
#
|
89
|
+
# Ransack.configure do |config|
|
90
|
+
# # Globally set the up arrow to an icon and the down arrow to unicode.
|
91
|
+
# config.custom_arrows = {
|
92
|
+
# up_arrow: '<i class="fa fa-long-arrow-up"></i>',
|
93
|
+
# down_arrow: 'U+02193'
|
94
|
+
# }
|
95
|
+
# end
|
96
|
+
#
|
97
|
+
def custom_arrows=(opts = {})
|
98
|
+
self.options[:up_arrow] = opts[:up_arrow].freeze if opts[:up_arrow]
|
99
|
+
self.options[:down_arrow] = opts[:down_arrow].freeze if opts[:down_arrow]
|
100
|
+
end
|
101
|
+
|
102
|
+
# Ransack sanitizes many values in your custom scopes into booleans.
|
103
|
+
# [1, '1', 't', 'T', 'true', 'TRUE'] all evaluate to true.
|
104
|
+
# [0, '0', 'f', 'F', 'false', 'FALSE'] all evaluate to false.
|
105
|
+
#
|
106
|
+
# This default may be globally overridden in an initializer file like
|
107
|
+
# `config/initializers/ransack.rb` as follows:
|
108
|
+
#
|
109
|
+
# Ransack.configure do |config|
|
110
|
+
# # Accept my custom scope values as what they are.
|
111
|
+
# config.sanitize_custom_scope_booleans = false
|
112
|
+
# end
|
113
|
+
#
|
114
|
+
def sanitize_custom_scope_booleans=(boolean)
|
115
|
+
self.options[:sanitize_scope_args] = boolean
|
116
|
+
end
|
117
|
+
|
78
118
|
# By default, Ransack displays sort order indicator arrows in sort links.
|
79
119
|
# The default may be globally overridden in an initializer file like
|
80
120
|
# `config/initializers/ransack.rb` as follows:
|
data/lib/ransack/search.rb
CHANGED
@@ -123,12 +123,18 @@ module Ransack
|
|
123
123
|
private
|
124
124
|
|
125
125
|
def add_scope(key, args)
|
126
|
+
sanitized_args = if Ransack.options[:sanitize_scope_args]
|
127
|
+
sanitized_scope_args(args)
|
128
|
+
else
|
129
|
+
args
|
130
|
+
end
|
131
|
+
|
126
132
|
if @context.scope_arity(key) == 1
|
127
133
|
@scope_args[key] = args.is_a?(Array) ? args[0] : args
|
128
134
|
else
|
129
|
-
@scope_args[key] = args.is_a?(Array) ?
|
135
|
+
@scope_args[key] = args.is_a?(Array) ? sanitized_args : args
|
130
136
|
end
|
131
|
-
@context.chain_scope(key,
|
137
|
+
@context.chain_scope(key, sanitized_args)
|
132
138
|
end
|
133
139
|
|
134
140
|
def sanitized_scope_args(args)
|
data/lib/ransack/version.rb
CHANGED
@@ -65,6 +65,27 @@ module Ransack
|
|
65
65
|
s = Person.ransack(term_cont: 'nomatch')
|
66
66
|
expect(s.result.to_a).to eq []
|
67
67
|
end
|
68
|
+
|
69
|
+
it 'makes aliases available to subclasses' do
|
70
|
+
yngwie = Musician.create!(name: 'Yngwie Malmsteen')
|
71
|
+
|
72
|
+
musicians = Musician.ransack(term_cont: 'ngw').result
|
73
|
+
expect(musicians).to eq([yngwie])
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'handles naming collisions gracefully' do
|
77
|
+
frank = Person.create!(name: 'Frank Stallone')
|
78
|
+
|
79
|
+
people = Person.ransack(term_cont: 'allon').result
|
80
|
+
expect(people).to eq([frank])
|
81
|
+
|
82
|
+
Class.new(Article) do
|
83
|
+
ransack_alias :term, :title
|
84
|
+
end
|
85
|
+
|
86
|
+
people = Person.ransack(term_cont: 'allon').result
|
87
|
+
expect(people).to eq([frank])
|
88
|
+
end
|
68
89
|
end
|
69
90
|
|
70
91
|
describe '#ransacker' do
|
@@ -274,8 +295,6 @@ module Ransack
|
|
274
295
|
end
|
275
296
|
|
276
297
|
describe '#ransackable_associations' do
|
277
|
-
before { pending "not implemented for mongoid" }
|
278
|
-
|
279
298
|
subject { Person.ransackable_associations }
|
280
299
|
|
281
300
|
it { should include 'parent' }
|
@@ -36,17 +36,73 @@ module Ransack
|
|
36
36
|
end
|
37
37
|
|
38
38
|
it 'changes default search key parameter' do
|
39
|
-
|
40
|
-
before = Ransack.options.clone
|
39
|
+
default = Ransack.options.clone
|
41
40
|
|
42
|
-
Ransack.configure
|
43
|
-
config.search_key = :query
|
44
|
-
end
|
41
|
+
Ransack.configure { |c| c.search_key = :query }
|
45
42
|
|
46
43
|
expect(Ransack.options[:search_key]).to eq :query
|
47
44
|
|
48
|
-
|
49
|
-
|
45
|
+
Ransack.options = default
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should have default values for arrows' do
|
49
|
+
expect(Ransack.options[:up_arrow]).to eq '▼'
|
50
|
+
expect(Ransack.options[:down_arrow]).to eq '▲'
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'changes the default value for the up arrow only' do
|
54
|
+
default, new_up_arrow = Ransack.options.clone, 'U+02191'
|
55
|
+
|
56
|
+
Ransack.configure { |c| c.custom_arrows = { up_arrow: new_up_arrow } }
|
57
|
+
|
58
|
+
expect(Ransack.options[:down_arrow]).to eq default[:down_arrow]
|
59
|
+
expect(Ransack.options[:up_arrow]).to eq new_up_arrow
|
60
|
+
|
61
|
+
Ransack.options = default
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'changes the default value for the down arrow only' do
|
65
|
+
default, new_down_arrow = Ransack.options.clone, '<i class="down"></i>'
|
66
|
+
|
67
|
+
Ransack.configure { |c| c.custom_arrows = { down_arrow: new_down_arrow } }
|
68
|
+
|
69
|
+
expect(Ransack.options[:up_arrow]).to eq default[:up_arrow]
|
70
|
+
expect(Ransack.options[:down_arrow]).to eq new_down_arrow
|
71
|
+
|
72
|
+
Ransack.options = default
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'changes the default value for both arrows' do
|
76
|
+
default = Ransack.options.clone
|
77
|
+
new_up_arrow = '<i class="fa fa-long-arrow-up"></i>'
|
78
|
+
new_down_arrow = 'U+02193'
|
79
|
+
|
80
|
+
Ransack.configure do |c|
|
81
|
+
c.custom_arrows = { up_arrow: new_up_arrow, down_arrow: new_down_arrow }
|
82
|
+
end
|
83
|
+
|
84
|
+
expect(Ransack.options[:up_arrow]).to eq new_up_arrow
|
85
|
+
expect(Ransack.options[:down_arrow]).to eq new_down_arrow
|
86
|
+
|
87
|
+
Ransack.options = default
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'consecutive arrow customizations respect previous customizations' do
|
91
|
+
default = Ransack.options.clone
|
92
|
+
|
93
|
+
Ransack.configure { |c| c.custom_arrows = { up_arrow: 'up' } }
|
94
|
+
expect(Ransack.options[:down_arrow]).to eq default[:down_arrow]
|
95
|
+
|
96
|
+
Ransack.configure { |c| c.custom_arrows = { down_arrow: 'DOWN' } }
|
97
|
+
expect(Ransack.options[:up_arrow]).to eq 'up'
|
98
|
+
|
99
|
+
Ransack.configure { |c| c.custom_arrows = { up_arrow: '<i>U-Arrow</i>' } }
|
100
|
+
expect(Ransack.options[:down_arrow]).to eq 'DOWN'
|
101
|
+
|
102
|
+
Ransack.configure { |c| c.custom_arrows = { down_arrow: 'down arrow-2' } }
|
103
|
+
expect(Ransack.options[:up_arrow]).to eq '<i>U-Arrow</i>'
|
104
|
+
|
105
|
+
Ransack.options = default
|
50
106
|
end
|
51
107
|
|
52
108
|
it 'adds predicates that take arrays, overriding compounds' do
|
@@ -76,8 +132,10 @@ module Ransack
|
|
76
132
|
)
|
77
133
|
end
|
78
134
|
|
79
|
-
expect(Ransack.predicates['test_in_predicate'].wants_array)
|
80
|
-
|
135
|
+
expect(Ransack.predicates['test_in_predicate'].wants_array)
|
136
|
+
.to eq true
|
137
|
+
expect(Ransack.predicates['test_not_in_predicate'].wants_array)
|
138
|
+
.to eq true
|
81
139
|
end
|
82
140
|
|
83
141
|
it 'explicitly does not want array for in/not_in predicates' do
|
@@ -94,8 +152,10 @@ module Ransack
|
|
94
152
|
)
|
95
153
|
end
|
96
154
|
|
97
|
-
expect(Ransack.predicates['test_in_predicate_no_array'].wants_array)
|
98
|
-
|
155
|
+
expect(Ransack.predicates['test_in_predicate_no_array'].wants_array)
|
156
|
+
.to eq false
|
157
|
+
expect(Ransack.predicates['test_not_in_predicate_no_array'].wants_array)
|
158
|
+
.to eq false
|
99
159
|
end
|
100
160
|
end
|
101
161
|
end
|
data/spec/mongoid/search_spec.rb
CHANGED
@@ -433,7 +433,6 @@ module Ransack
|
|
433
433
|
end
|
434
434
|
|
435
435
|
context 'with joins' do
|
436
|
-
before { pending 'not implemented for mongoid' }
|
437
436
|
it 'allows chaining to access nested conditions' do
|
438
437
|
@s.groupings = [
|
439
438
|
{ :m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie' }
|
@@ -65,25 +65,31 @@ module Ransack
|
|
65
65
|
expect(s.result.to_sql).to (include 'age > 18')
|
66
66
|
end
|
67
67
|
|
68
|
-
# TODO: Implement a way to pass true/false values like 0 or 1 to
|
69
|
-
# scopes (e.g. with `in` / `not_in` predicates), without Ransack
|
70
|
-
# converting them to true/false boolean values instead.
|
71
|
-
|
72
|
-
# it 'passes true values to scopes', focus: true do
|
73
|
-
# s = Person.ransack('over_age' => 1)
|
74
|
-
# expect(s.result.to_sql).to (include 'age > 1')
|
75
|
-
# end
|
76
|
-
|
77
|
-
# it 'passes false values to scopes', focus: true do
|
78
|
-
# s = Person.ransack('over_age' => 0)
|
79
|
-
# expect(s.result.to_sql).to (include 'age > 0')
|
80
|
-
# end
|
81
|
-
|
82
68
|
it 'chains scopes' do
|
83
69
|
s = Person.ransack('over_age' => 18, 'active' => true)
|
84
70
|
expect(s.result.to_sql).to (include 'age > 18')
|
85
71
|
expect(s.result.to_sql).to (include 'active = 1')
|
86
72
|
end
|
73
|
+
|
74
|
+
context "with sanitize_custom_scope_booleans set to false" do
|
75
|
+
before(:all) do
|
76
|
+
Ransack.configure { |c| c.sanitize_custom_scope_booleans = false }
|
77
|
+
end
|
78
|
+
|
79
|
+
after(:all) do
|
80
|
+
Ransack.configure { |c| c.sanitize_custom_scope_booleans = true }
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'passes true values to scopes' do
|
84
|
+
s = Person.ransack('over_age' => 1)
|
85
|
+
expect(s.result.to_sql).to (include 'age > 1')
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'passes false values to scopes' do
|
89
|
+
s = Person.ransack('over_age' => 0)
|
90
|
+
expect(s.result.to_sql).to (include 'age > 0')
|
91
|
+
end
|
92
|
+
end
|
87
93
|
end
|
88
94
|
|
89
95
|
it 'does not raise exception for string :params argument' do
|
@@ -190,6 +196,27 @@ module Ransack
|
|
190
196
|
s = Person.ransack(daddy_eq: 'Drake')
|
191
197
|
expect(s.result.to_a).to eq []
|
192
198
|
end
|
199
|
+
|
200
|
+
it 'makes aliases available to subclasses' do
|
201
|
+
yngwie = Musician.create!(name: 'Yngwie Malmsteen')
|
202
|
+
|
203
|
+
musicians = Musician.ransack(term_cont: 'ngw').result
|
204
|
+
expect(musicians).to eq([yngwie])
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'handles naming collisions gracefully' do
|
208
|
+
frank = Person.create!(name: 'Frank Stallone')
|
209
|
+
|
210
|
+
people = Person.ransack(term_cont: 'allon').result
|
211
|
+
expect(people).to eq([frank])
|
212
|
+
|
213
|
+
Class.new(Article) do
|
214
|
+
ransack_alias :term, :title
|
215
|
+
end
|
216
|
+
|
217
|
+
people = Person.ransack(term_cont: 'allon').result
|
218
|
+
expect(people).to eq([frank])
|
219
|
+
end
|
193
220
|
end
|
194
221
|
|
195
222
|
describe '#ransacker' do
|
@@ -3,9 +3,7 @@ require 'spec_helper'
|
|
3
3
|
module Ransack
|
4
4
|
describe Configuration do
|
5
5
|
it 'yields Ransack on configure' do
|
6
|
-
Ransack.configure
|
7
|
-
expect(config).to eq Ransack
|
8
|
-
end
|
6
|
+
Ransack.configure { |config| expect(config).to eq Ransack }
|
9
7
|
end
|
10
8
|
|
11
9
|
it 'adds predicates' do
|
@@ -38,17 +36,73 @@ module Ransack
|
|
38
36
|
end
|
39
37
|
|
40
38
|
it 'changes default search key parameter' do
|
41
|
-
|
42
|
-
before = Ransack.options.clone
|
39
|
+
default = Ransack.options.clone
|
43
40
|
|
44
|
-
Ransack.configure
|
45
|
-
config.search_key = :query
|
46
|
-
end
|
41
|
+
Ransack.configure { |c| c.search_key = :query }
|
47
42
|
|
48
43
|
expect(Ransack.options[:search_key]).to eq :query
|
49
44
|
|
50
|
-
|
51
|
-
|
45
|
+
Ransack.options = default
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should have default values for arrows' do
|
49
|
+
expect(Ransack.options[:up_arrow]).to eq '▼'
|
50
|
+
expect(Ransack.options[:down_arrow]).to eq '▲'
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'changes the default value for the up arrow only' do
|
54
|
+
default, new_up_arrow = Ransack.options.clone, 'U+02191'
|
55
|
+
|
56
|
+
Ransack.configure { |c| c.custom_arrows = { up_arrow: new_up_arrow } }
|
57
|
+
|
58
|
+
expect(Ransack.options[:down_arrow]).to eq default[:down_arrow]
|
59
|
+
expect(Ransack.options[:up_arrow]).to eq new_up_arrow
|
60
|
+
|
61
|
+
Ransack.options = default
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'changes the default value for the down arrow only' do
|
65
|
+
default, new_down_arrow = Ransack.options.clone, '<i class="down"></i>'
|
66
|
+
|
67
|
+
Ransack.configure { |c| c.custom_arrows = { down_arrow: new_down_arrow } }
|
68
|
+
|
69
|
+
expect(Ransack.options[:up_arrow]).to eq default[:up_arrow]
|
70
|
+
expect(Ransack.options[:down_arrow]).to eq new_down_arrow
|
71
|
+
|
72
|
+
Ransack.options = default
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'changes the default value for both arrows' do
|
76
|
+
default = Ransack.options.clone
|
77
|
+
new_up_arrow = '<i class="fa fa-long-arrow-up"></i>'
|
78
|
+
new_down_arrow = 'U+02193'
|
79
|
+
|
80
|
+
Ransack.configure do |c|
|
81
|
+
c.custom_arrows = { up_arrow: new_up_arrow, down_arrow: new_down_arrow }
|
82
|
+
end
|
83
|
+
|
84
|
+
expect(Ransack.options[:up_arrow]).to eq new_up_arrow
|
85
|
+
expect(Ransack.options[:down_arrow]).to eq new_down_arrow
|
86
|
+
|
87
|
+
Ransack.options = default
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'consecutive arrow customizations respect previous customizations' do
|
91
|
+
default = Ransack.options.clone
|
92
|
+
|
93
|
+
Ransack.configure { |c| c.custom_arrows = { up_arrow: 'up' } }
|
94
|
+
expect(Ransack.options[:down_arrow]).to eq default[:down_arrow]
|
95
|
+
|
96
|
+
Ransack.configure { |c| c.custom_arrows = { down_arrow: 'DOWN' } }
|
97
|
+
expect(Ransack.options[:up_arrow]).to eq 'up'
|
98
|
+
|
99
|
+
Ransack.configure { |c| c.custom_arrows = { up_arrow: '<i>U-Arrow</i>' } }
|
100
|
+
expect(Ransack.options[:down_arrow]).to eq 'DOWN'
|
101
|
+
|
102
|
+
Ransack.configure { |c| c.custom_arrows = { down_arrow: 'down arrow-2' } }
|
103
|
+
expect(Ransack.options[:up_arrow]).to eq '<i>U-Arrow</i>'
|
104
|
+
|
105
|
+
Ransack.options = default
|
52
106
|
end
|
53
107
|
|
54
108
|
it 'adds predicates that take arrays, overriding compounds' do
|
@@ -78,8 +132,10 @@ module Ransack
|
|
78
132
|
)
|
79
133
|
end
|
80
134
|
|
81
|
-
expect(Ransack.predicates['test_in_predicate'].wants_array)
|
82
|
-
|
135
|
+
expect(Ransack.predicates['test_in_predicate'].wants_array)
|
136
|
+
.to eq true
|
137
|
+
expect(Ransack.predicates['test_not_in_predicate'].wants_array)
|
138
|
+
.to eq true
|
83
139
|
end
|
84
140
|
|
85
141
|
it 'explicitly does not want array for in/not_in predicates' do
|
@@ -96,8 +152,10 @@ module Ransack
|
|
96
152
|
)
|
97
153
|
end
|
98
154
|
|
99
|
-
expect(Ransack.predicates['test_in_predicate_no_array'].wants_array)
|
100
|
-
|
155
|
+
expect(Ransack.predicates['test_in_predicate_no_array'].wants_array)
|
156
|
+
.to eq false
|
157
|
+
expect(Ransack.predicates['test_not_in_predicate_no_array'].wants_array)
|
158
|
+
.to eq false
|
101
159
|
end
|
102
160
|
end
|
103
161
|
end
|
@@ -649,10 +649,57 @@ module Ransack
|
|
649
649
|
it { should match /Full Name ▼/ }
|
650
650
|
end
|
651
651
|
|
652
|
-
describe '#sort_link with config set
|
652
|
+
describe '#sort_link with config set with custom up_arrow' do
|
653
|
+
before do
|
654
|
+
Ransack.configure { |c| c.custom_arrows = { up_arrow: "\u{1F446}" } }
|
655
|
+
end
|
656
|
+
|
657
|
+
after do
|
658
|
+
Ransack.configure { |c| c.custom_arrows = { up_arrow: "▼" } }
|
659
|
+
end
|
660
|
+
|
661
|
+
subject { @controller.view_context
|
662
|
+
.sort_link(
|
663
|
+
[:main_app, Person.search(sorts: ['name desc'])],
|
664
|
+
:name,
|
665
|
+
controller: 'people',
|
666
|
+
hide_indicator: false
|
667
|
+
)
|
668
|
+
}
|
669
|
+
|
670
|
+
it { should match /Full Name \u{1F446}/ }
|
671
|
+
end
|
672
|
+
|
673
|
+
describe '#sort_link with config set with custom down_arrow' do
|
674
|
+
before do
|
675
|
+
Ransack.configure { |c| c.custom_arrows = { down_arrow: "\u{1F447}" } }
|
676
|
+
end
|
677
|
+
|
678
|
+
after do
|
679
|
+
Ransack.configure { |c| c.custom_arrows = { down_arrow: "▲" } }
|
680
|
+
end
|
681
|
+
|
682
|
+
subject { @controller.view_context
|
683
|
+
.sort_link(
|
684
|
+
[:main_app, Person.search(sorts: ['name asc'])],
|
685
|
+
:name,
|
686
|
+
controller: 'people',
|
687
|
+
hide_indicator: false
|
688
|
+
)
|
689
|
+
}
|
690
|
+
|
691
|
+
it { should match /Full Name \u{1F447}/ }
|
692
|
+
end
|
693
|
+
|
694
|
+
describe '#sort_link with config set to hide arrows' do
|
653
695
|
before do
|
654
696
|
Ransack.configure { |c| c.hide_sort_order_indicators = true }
|
655
697
|
end
|
698
|
+
|
699
|
+
after do
|
700
|
+
Ransack.configure { |c| c.hide_sort_order_indicators = false }
|
701
|
+
end
|
702
|
+
|
656
703
|
subject { @controller.view_context
|
657
704
|
.sort_link(
|
658
705
|
[:main_app, Person.search(sorts: ['name desc'])],
|
@@ -660,13 +707,15 @@ module Ransack
|
|
660
707
|
controller: 'people'
|
661
708
|
)
|
662
709
|
}
|
710
|
+
|
663
711
|
it { should_not match /▼|▲/ }
|
664
712
|
end
|
665
713
|
|
666
|
-
describe '#sort_link with config set to
|
714
|
+
describe '#sort_link with config set to show arrows (default setting)' do
|
667
715
|
before do
|
668
716
|
Ransack.configure { |c| c.hide_sort_order_indicators = false }
|
669
717
|
end
|
718
|
+
|
670
719
|
subject { @controller.view_context
|
671
720
|
.sort_link(
|
672
721
|
[:main_app, Person.search(sorts: ['name desc'])],
|
@@ -674,9 +723,62 @@ module Ransack
|
|
674
723
|
controller: 'people'
|
675
724
|
)
|
676
725
|
}
|
726
|
+
|
677
727
|
it { should match /Full Name ▼/ }
|
678
728
|
end
|
679
729
|
|
730
|
+
describe '#sort_link w/config to hide arrows + custom arrow, hides all' do
|
731
|
+
before do
|
732
|
+
Ransack.configure do |c|
|
733
|
+
c.hide_sort_order_indicators = true
|
734
|
+
c.custom_arrows = { down_arrow: 'down' }
|
735
|
+
end
|
736
|
+
end
|
737
|
+
|
738
|
+
after do
|
739
|
+
Ransack.configure do |c|
|
740
|
+
c.hide_sort_order_indicators = false
|
741
|
+
c.custom_arrows = { down_arrow: '▲' }
|
742
|
+
end
|
743
|
+
end
|
744
|
+
|
745
|
+
subject { @controller.view_context
|
746
|
+
.sort_link(
|
747
|
+
[:main_app, Person.search(sorts: ['name desc'])],
|
748
|
+
:name,
|
749
|
+
controller: 'people'
|
750
|
+
)
|
751
|
+
}
|
752
|
+
|
753
|
+
it { should_not match /▼|down/ }
|
754
|
+
end
|
755
|
+
|
756
|
+
describe '#sort_link with config set to show arrows + custom arrow' do
|
757
|
+
before do
|
758
|
+
Ransack.configure do |c|
|
759
|
+
c.hide_sort_order_indicators = false
|
760
|
+
c.custom_arrows = { up_arrow: 'up-value' }
|
761
|
+
end
|
762
|
+
end
|
763
|
+
|
764
|
+
after do
|
765
|
+
Ransack.configure do |c|
|
766
|
+
c.hide_sort_order_indicators = false
|
767
|
+
c.custom_arrows = { up_arrow: '▼' }
|
768
|
+
end
|
769
|
+
end
|
770
|
+
|
771
|
+
subject { @controller.view_context
|
772
|
+
.sort_link(
|
773
|
+
[:main_app, Person.search(sorts: ['name desc'])],
|
774
|
+
:name,
|
775
|
+
controller: 'people'
|
776
|
+
)
|
777
|
+
}
|
778
|
+
|
779
|
+
it { should match /▲|up-value/ }
|
780
|
+
end
|
781
|
+
|
680
782
|
describe '#sort_link with a block' do
|
681
783
|
subject { @controller.view_context
|
682
784
|
.sort_link(
|
@@ -329,6 +329,28 @@ module Ransack
|
|
329
329
|
field = "#{quote_table_name("people")}.#{quote_column_name("name")}"
|
330
330
|
expect(@s.result.to_sql).to match /#{field} IS NULL/
|
331
331
|
end
|
332
|
+
|
333
|
+
describe 'with association qeury' do
|
334
|
+
it 'generates a value IS NOT NULL query' do
|
335
|
+
@s.comments_id_not_null = true
|
336
|
+
sql = @s.result.to_sql
|
337
|
+
parent_field = "#{quote_table_name("people")}.#{quote_column_name("id")}"
|
338
|
+
expect(sql).to match /#{parent_field} IN/
|
339
|
+
field = "#{quote_table_name("comments")}.#{quote_column_name("id")}"
|
340
|
+
expect(sql).to match /#{field} IS NOT NULL/
|
341
|
+
expect(sql).not_to match /AND NOT/
|
342
|
+
end
|
343
|
+
|
344
|
+
it 'generates a value IS NULL query when assigned false' do
|
345
|
+
@s.comments_id_not_null = false
|
346
|
+
sql = @s.result.to_sql
|
347
|
+
parent_field = "#{quote_table_name("people")}.#{quote_column_name("id")}"
|
348
|
+
expect(sql).to match /#{parent_field} NOT IN/
|
349
|
+
field = "#{quote_table_name("comments")}.#{quote_column_name("id")}"
|
350
|
+
expect(sql).to match /#{field} IS NULL/
|
351
|
+
expect(sql).to match /AND NOT/
|
352
|
+
end
|
353
|
+
end
|
332
354
|
end
|
333
355
|
|
334
356
|
describe 'present' do
|
data/spec/support/schema.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ransack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.8.
|
4
|
+
version: 1.8.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ernie Miller
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2017-06-15 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: actionpack
|
@@ -317,7 +317,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
317
317
|
version: '0'
|
318
318
|
requirements: []
|
319
319
|
rubyforge_project: ransack
|
320
|
-
rubygems_version: 2.
|
320
|
+
rubygems_version: 2.5.2
|
321
321
|
signing_key:
|
322
322
|
specification_version: 4
|
323
323
|
summary: Object-based searching for Active Record and Mongoid (currently).
|