ransack 4.1.1 → 4.4.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/README.md +5 -3
- data/lib/polyamorous/activerecord/join_association_7_2.rb +55 -0
- data/lib/polyamorous/polyamorous.rb +5 -1
- data/lib/ransack/adapters/active_record/context.rb +32 -5
- data/lib/ransack/constants.rb +1 -1
- data/lib/ransack/context.rb +7 -4
- data/lib/ransack/helpers/form_builder.rb +6 -7
- data/lib/ransack/helpers/form_helper.rb +86 -20
- data/lib/ransack/invalid_search_error.rb +3 -0
- data/lib/ransack/locale/ja.yml +51 -51
- data/lib/ransack/locale/ko.yml +70 -0
- data/lib/ransack/locale/uk.yml +72 -0
- data/lib/ransack/nodes/condition.rb +39 -7
- data/lib/ransack/nodes/grouping.rb +1 -1
- data/lib/ransack/nodes/sort.rb +1 -1
- data/lib/ransack/nodes/value.rb +9 -1
- data/lib/ransack/search.rb +4 -3
- data/lib/ransack/version.rb +1 -1
- data/lib/ransack.rb +9 -0
- data/spec/polyamorous/join_association_spec.rb +0 -1
- data/spec/polyamorous/join_dependency_spec.rb +0 -1
- data/spec/ransack/adapters/active_record/base_spec.rb +106 -3
- data/spec/ransack/adapters/active_record/context_spec.rb +72 -0
- data/spec/ransack/helpers/form_builder_spec.rb +0 -2
- data/spec/ransack/helpers/form_helper_spec.rb +219 -5
- data/spec/ransack/nodes/condition_spec.rb +230 -0
- data/spec/ransack/nodes/grouping_spec.rb +2 -2
- data/spec/ransack/nodes/value_spec.rb +12 -1
- data/spec/ransack/predicate_spec.rb +16 -9
- data/spec/ransack/search_spec.rb +121 -1
- data/spec/ransack/translate_spec.rb +0 -1
- data/spec/spec_helper.rb +2 -3
- data/spec/support/schema.rb +42 -0
- metadata +17 -86
- data/.github/FUNDING.yml +0 -3
- data/.github/SECURITY.md +0 -12
- data/.github/workflows/codeql.yml +0 -72
- data/.github/workflows/cronjob.yml +0 -99
- data/.github/workflows/deploy.yml +0 -35
- data/.github/workflows/rubocop.yml +0 -20
- data/.github/workflows/test-deploy.yml +0 -29
- data/.github/workflows/test.yml +0 -131
- data/.gitignore +0 -7
- data/.nojekyll +0 -0
- data/.rubocop.yml +0 -50
- data/CHANGELOG.md +0 -1176
- data/CONTRIBUTING.md +0 -171
- data/Gemfile +0 -53
- data/Rakefile +0 -24
- data/bug_report_templates/test-ransack-scope-and-column-same-name.rb +0 -78
- data/bug_report_templates/test-ransacker-arel-present-predicate.rb +0 -75
- data/docs/.gitignore +0 -19
- data/docs/.nojekyll +0 -0
- data/docs/babel.config.js +0 -3
- data/docs/blog/2022-03-27-ransack-3.0.0.md +0 -20
- data/docs/docs/getting-started/_category_.json +0 -4
- data/docs/docs/getting-started/advanced-mode.md +0 -46
- data/docs/docs/getting-started/configuration.md +0 -47
- data/docs/docs/getting-started/search-matches.md +0 -67
- data/docs/docs/getting-started/simple-mode.md +0 -288
- data/docs/docs/getting-started/sorting.md +0 -71
- data/docs/docs/getting-started/using-predicates.md +0 -282
- data/docs/docs/going-further/_category_.json +0 -4
- data/docs/docs/going-further/acts-as-taggable-on.md +0 -114
- data/docs/docs/going-further/associations.md +0 -70
- data/docs/docs/going-further/custom-predicates.md +0 -52
- data/docs/docs/going-further/documentation.md +0 -43
- data/docs/docs/going-further/exporting-to-csv.md +0 -49
- data/docs/docs/going-further/external-guides.md +0 -57
- data/docs/docs/going-further/form-customisation.md +0 -63
- data/docs/docs/going-further/i18n.md +0 -53
- data/docs/docs/going-further/img/create_release.png +0 -0
- data/docs/docs/going-further/merging-searches.md +0 -41
- data/docs/docs/going-further/other-notes.md +0 -428
- data/docs/docs/going-further/polymorphic-search.md +0 -46
- data/docs/docs/going-further/ransackers.md +0 -331
- data/docs/docs/going-further/release_process.md +0 -36
- data/docs/docs/going-further/saving-queries.md +0 -82
- data/docs/docs/going-further/searching-postgres.md +0 -57
- data/docs/docs/going-further/wiki-contributors.md +0 -82
- data/docs/docs/intro.md +0 -99
- data/docs/docusaurus.config.js +0 -120
- data/docs/package.json +0 -42
- data/docs/sidebars.js +0 -31
- data/docs/src/components/HomepageFeatures/index.js +0 -64
- data/docs/src/components/HomepageFeatures/styles.module.css +0 -11
- data/docs/src/css/custom.css +0 -39
- data/docs/src/pages/index.module.css +0 -23
- data/docs/src/pages/markdown-page.md +0 -7
- 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 +0 -1
- 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 +0 -171
- data/docs/static/img/undraw_docusaurus_react.svg +0 -170
- data/docs/static/img/undraw_docusaurus_tree.svg +0 -40
- data/docs/static/logo/ransack-h.png +0 -0
- data/docs/static/logo/ransack-h.svg +0 -34
- data/docs/static/logo/ransack-v.png +0 -0
- data/docs/static/logo/ransack-v.svg +0 -34
- data/docs/static/logo/ransack.png +0 -0
- data/docs/static/logo/ransack.svg +0 -21
- data/docs/yarn.lock +0 -8879
- data/ransack.gemspec +0 -26
@@ -1,288 +0,0 @@
|
|
1
|
-
---
|
2
|
-
sidebar_position: 1
|
3
|
-
title: Simple mode
|
4
|
-
---
|
5
|
-
|
6
|
-
# Simple Mode
|
7
|
-
|
8
|
-
Ransack can be used in one of two modes, simple or advanced. For
|
9
|
-
searching/filtering not requiring complex boolean logic, Ransack's simple
|
10
|
-
mode should meet your needs.
|
11
|
-
|
12
|
-
## In your controller
|
13
|
-
|
14
|
-
```ruby
|
15
|
-
def index
|
16
|
-
@q = Person.ransack(params[:q])
|
17
|
-
@people = @q.result(distinct: true)
|
18
|
-
end
|
19
|
-
```
|
20
|
-
or without `distinct: true`, for sorting on an associated table's columns (in
|
21
|
-
this example, with preloading each Person's Articles and pagination):
|
22
|
-
|
23
|
-
```ruby
|
24
|
-
def index
|
25
|
-
@q = Person.ransack(params[:q])
|
26
|
-
@people = @q.result.includes(:articles).page(params[:page])
|
27
|
-
end
|
28
|
-
```
|
29
|
-
|
30
|
-
:::caution
|
31
|
-
By default, searching and sorting are authorized on any column of your model. See [Authorization (allowlisting/denylisting)](/going-further/other-notes.md#authorization-allowlistingdenylisting) on how to prevent this.
|
32
|
-
:::
|
33
|
-
|
34
|
-
### Default search options
|
35
|
-
|
36
|
-
#### Search parameter
|
37
|
-
|
38
|
-
Ransack uses a default `:q` param key for search params. This may be changed by
|
39
|
-
setting the `search_key` option in a Ransack initializer file (typically
|
40
|
-
`config/initializers/ransack.rb`):
|
41
|
-
|
42
|
-
```ruby
|
43
|
-
Ransack.configure do |c|
|
44
|
-
# Change default search parameter key name.
|
45
|
-
# Default key name is :q
|
46
|
-
c.search_key = :query
|
47
|
-
end
|
48
|
-
```
|
49
|
-
|
50
|
-
#### String search
|
51
|
-
|
52
|
-
After version 2.4.0 when searching a string query Ransack by default strips all whitespace around the query string.
|
53
|
-
This may be disabled by setting the `strip_whitespace` option in a Ransack initializer file:
|
54
|
-
|
55
|
-
```ruby
|
56
|
-
Ransack.configure do |c|
|
57
|
-
# Change whitespace stripping behavior.
|
58
|
-
# Default is true
|
59
|
-
c.strip_whitespace = false
|
60
|
-
end
|
61
|
-
```
|
62
|
-
|
63
|
-
## In your view
|
64
|
-
|
65
|
-
The two primary Ransack view helpers are `search_form_for` and `sort_link`,
|
66
|
-
which are defined in
|
67
|
-
[Ransack::Helpers::FormHelper](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/helpers/form_helper.rb).
|
68
|
-
|
69
|
-
### Form helper
|
70
|
-
|
71
|
-
Ransack's `search_form_for` helper replaces `form_for` for creating the view search form
|
72
|
-
|
73
|
-
```erb
|
74
|
-
<%= search_form_for @q do |f| %>
|
75
|
-
|
76
|
-
# Search if the name field contains...
|
77
|
-
<%= f.label :name_cont %>
|
78
|
-
<%= f.search_field :name_cont %>
|
79
|
-
|
80
|
-
# Search if an associated articles.title starts with...
|
81
|
-
<%= f.label :articles_title_start %>
|
82
|
-
<%= f.search_field :articles_title_start %>
|
83
|
-
|
84
|
-
# Attributes may be chained. Search multiple attributes for one value...
|
85
|
-
<%= f.label :name_or_description_or_email_or_articles_title_cont %>
|
86
|
-
<%= f.search_field :name_or_description_or_email_or_articles_title_cont %>
|
87
|
-
|
88
|
-
<%= f.submit %>
|
89
|
-
<% end %>
|
90
|
-
```
|
91
|
-
|
92
|
-
The argument of `f.search_field` has to be in this form:
|
93
|
-
`attribute_name[_or_attribute_name]..._predicate`
|
94
|
-
|
95
|
-
where `[_or_another_attribute_name]...` means any repetition of `_or_` plus the name of the attribute.
|
96
|
-
|
97
|
-
`cont` (contains) and `start` (starts with) are just two of the available
|
98
|
-
search predicates.
|
99
|
-
|
100
|
-
The `search_form_for` answer format can be set like this:
|
101
|
-
|
102
|
-
```erb
|
103
|
-
<%= search_form_for(@q, format: :pdf) do |f| %>
|
104
|
-
|
105
|
-
<%= search_form_for(@q, format: :json) do |f| %>
|
106
|
-
```
|
107
|
-
|
108
|
-
### Search link helper
|
109
|
-
|
110
|
-
Ransack's `sort_link` helper creates table headers that are sortable links
|
111
|
-
|
112
|
-
```erb
|
113
|
-
<%= sort_link(@q, :name) %>
|
114
|
-
```
|
115
|
-
Additional options can be passed after the column parameter, like a different
|
116
|
-
column title or a default sort order.
|
117
|
-
|
118
|
-
If the first option after the column parameter is a String, it's considered a
|
119
|
-
custom label for the link:
|
120
|
-
|
121
|
-
```erb
|
122
|
-
<%= sort_link(@q, :name, 'Last Name', default_order: :desc) %>
|
123
|
-
```
|
124
|
-
|
125
|
-
You can use a block if the link markup is hard to fit into the label parameter:
|
126
|
-
|
127
|
-
```erb
|
128
|
-
<%= sort_link(@q, :name) do %>
|
129
|
-
<strong>Player Name</strong>
|
130
|
-
<% end %>
|
131
|
-
```
|
132
|
-
|
133
|
-
With a polymorphic association, you may need to specify the name of the link
|
134
|
-
explicitly to avoid an `uninitialized constant Model::Xxxable` error (see issue
|
135
|
-
[#421](https://github.com/activerecord-hackery/ransack/issues/421)):
|
136
|
-
|
137
|
-
```erb
|
138
|
-
<%= sort_link(@q, :xxxable_of_Ymodel_type_some_attribute, 'Attribute Name') %>
|
139
|
-
```
|
140
|
-
|
141
|
-
If the first option after the column parameter and/or the label parameter is an
|
142
|
-
Array, it will be used for sorting on multiple fields:
|
143
|
-
|
144
|
-
```erb
|
145
|
-
<%= sort_link(@q, :last_name, [:last_name, 'first_name asc'], 'Last Name') %>
|
146
|
-
```
|
147
|
-
|
148
|
-
In the example above, clicking the link will sort by `last_name` and then
|
149
|
-
`first_name`. Specifying the sort direction on a field in the array tells
|
150
|
-
Ransack to _always_ sort that particular field in the specified direction.
|
151
|
-
|
152
|
-
Multiple `default_order` fields may also be specified with a trailing options
|
153
|
-
Hash:
|
154
|
-
|
155
|
-
```erb
|
156
|
-
<%= sort_link(@q, :last_name, %i(last_name first_name),
|
157
|
-
default_order: { last_name: 'asc', first_name: 'desc' }) %>
|
158
|
-
```
|
159
|
-
|
160
|
-
This example toggles the sort directions of both fields, by default
|
161
|
-
initially sorting the `last_name` field by ascending order, and the
|
162
|
-
`first_name` field by descending order.
|
163
|
-
|
164
|
-
In the case that you wish to sort by some complex value, such as the result
|
165
|
-
of a SQL function, you may do so using scopes. In your model, define scopes
|
166
|
-
whose names line up with the name of the virtual field you wish to sort by,
|
167
|
-
as so:
|
168
|
-
|
169
|
-
```ruby
|
170
|
-
class Person < ActiveRecord::Base
|
171
|
-
scope :sort_by_reverse_name_asc, lambda { order("REVERSE(name) ASC") }
|
172
|
-
scope :sort_by_reverse_name_desc, lambda { order("REVERSE(name) DESC") }
|
173
|
-
...
|
174
|
-
```
|
175
|
-
|
176
|
-
and you can then sort by this virtual field:
|
177
|
-
|
178
|
-
```erb
|
179
|
-
<%= sort_link(@q, :reverse_name) %>
|
180
|
-
```
|
181
|
-
|
182
|
-
The trailing options Hash can also be used for passing additional options to the
|
183
|
-
generated link, like `class:`.
|
184
|
-
|
185
|
-
The sort link order indicator arrows may be globally customized by setting a
|
186
|
-
`custom_arrows` option in an initializer file like
|
187
|
-
`config/initializers/ransack.rb`.
|
188
|
-
|
189
|
-
You can also enable a `default_arrow` which is displayed on all sortable fields
|
190
|
-
which are not currently used in the sorting. This is disabled by default so
|
191
|
-
nothing will be displayed:
|
192
|
-
|
193
|
-
```ruby
|
194
|
-
Ransack.configure do |c|
|
195
|
-
c.custom_arrows = {
|
196
|
-
up_arrow: '<i class="custom-up-arrow-icon"></i>',
|
197
|
-
down_arrow: 'U+02193',
|
198
|
-
default_arrow: '<i class="default-arrow-icon"></i>'
|
199
|
-
}
|
200
|
-
end
|
201
|
-
```
|
202
|
-
|
203
|
-
All sort links may be displayed without the order indicator
|
204
|
-
arrows by setting `hide_sort_order_indicators` to true in the initializer file.
|
205
|
-
Note that this hides the arrows even if they were customized:
|
206
|
-
|
207
|
-
```ruby
|
208
|
-
Ransack.configure do |c|
|
209
|
-
c.hide_sort_order_indicators = true
|
210
|
-
end
|
211
|
-
```
|
212
|
-
|
213
|
-
Without setting it globally, individual sort links may be displayed without
|
214
|
-
the order indicator arrow by passing `hide_indicator: true` in the sort link:
|
215
|
-
|
216
|
-
```erb
|
217
|
-
<%= sort_link(@q, :name, hide_indicator: true) %>
|
218
|
-
```
|
219
|
-
|
220
|
-
### sort_url
|
221
|
-
|
222
|
-
Ransack's `sort_url` helper is like a `sort_link` but returns only the url
|
223
|
-
|
224
|
-
`sort_url` has the same API as `sort_link`:
|
225
|
-
|
226
|
-
```erb
|
227
|
-
<%= sort_url(@q, :name, default_order: :desc) %>
|
228
|
-
```
|
229
|
-
|
230
|
-
```erb
|
231
|
-
<%= sort_url(@q, :last_name, [:last_name, 'first_name asc']) %>
|
232
|
-
```
|
233
|
-
|
234
|
-
```erb
|
235
|
-
<%= sort_url(@q, :last_name, %i(last_name first_name),
|
236
|
-
default_order: { last_name: 'asc', first_name: 'desc' }) %>
|
237
|
-
```
|
238
|
-
|
239
|
-
### PostgreSQL's sort option
|
240
|
-
|
241
|
-
The `NULLS FIRST` and `NULLS LAST` options can be used to determine whether nulls appear before or after non-null values in the sort ordering.
|
242
|
-
|
243
|
-
You may want to configure it like this:
|
244
|
-
|
245
|
-
```ruby
|
246
|
-
Ransack.configure do |c|
|
247
|
-
c.postgres_fields_sort_option = :nulls_first # or :nulls_last
|
248
|
-
end
|
249
|
-
```
|
250
|
-
|
251
|
-
To treat nulls as having the lowest or highest value respectively. To force nulls to always be first or last, use
|
252
|
-
|
253
|
-
```ruby
|
254
|
-
Ransack.configure do |c|
|
255
|
-
c.postgres_fields_sort_option = :nulls_always_first # or :nulls_always_last
|
256
|
-
end
|
257
|
-
```
|
258
|
-
|
259
|
-
See this feature: https://www.postgresql.org/docs/13/queries-order.html
|
260
|
-
|
261
|
-
#### Case Insensitive Sorting in PostgreSQL
|
262
|
-
|
263
|
-
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:
|
264
|
-
|
265
|
-
```ruby
|
266
|
-
module RansackObject
|
267
|
-
|
268
|
-
def self.included(base)
|
269
|
-
base.columns.each do |column|
|
270
|
-
if column.type == :string
|
271
|
-
base.ransacker column.name.to_sym, type: :string do
|
272
|
-
Arel.sql("lower(#{base.table_name}.#{column.name})")
|
273
|
-
end
|
274
|
-
end
|
275
|
-
end
|
276
|
-
end
|
277
|
-
end
|
278
|
-
```
|
279
|
-
|
280
|
-
```ruby
|
281
|
-
class UserWithManyAttributes < ActiveRecord::Base
|
282
|
-
include RansackObject
|
283
|
-
end
|
284
|
-
```
|
285
|
-
|
286
|
-
If this approach is taken, it is advisable to [add a functional index](https://www.postgresql.org/docs/13/citext.html).
|
287
|
-
|
288
|
-
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).
|
@@ -1,71 +0,0 @@
|
|
1
|
-
---
|
2
|
-
title: Sorting
|
3
|
-
---
|
4
|
-
|
5
|
-
|
6
|
-
# Sorting
|
7
|
-
|
8
|
-
## Sorting in the View
|
9
|
-
|
10
|
-
You can add a form to capture sorting and filtering options together.
|
11
|
-
|
12
|
-
```erb
|
13
|
-
# app/views/posts/index.html.erb
|
14
|
-
|
15
|
-
<%= search_form_for @q do |f| %>
|
16
|
-
<%= f.label :title_cont %>
|
17
|
-
<%= f.search_field :title_cont %>
|
18
|
-
|
19
|
-
<%= f.submit "Search" %>
|
20
|
-
<% end %>
|
21
|
-
|
22
|
-
<table>
|
23
|
-
<thead>
|
24
|
-
<tr>
|
25
|
-
<th><%= sort_link(@q, :title, "Title") %></th>
|
26
|
-
<th><%= sort_link(@q, :category, "Category") %></th>
|
27
|
-
<th><%= sort_link(@q, :created_at, "Created at") %></th>
|
28
|
-
</tr>
|
29
|
-
</thead>
|
30
|
-
|
31
|
-
<tbody>
|
32
|
-
<% @posts.each do |post| %>
|
33
|
-
<tr>
|
34
|
-
<td><%= post.title %></td>
|
35
|
-
<td><%= post.category %></td>
|
36
|
-
<td><%= post.created_at.to_s(:long) %></td>
|
37
|
-
</tr>
|
38
|
-
<% end %>
|
39
|
-
</tbody>
|
40
|
-
</table>
|
41
|
-
```
|
42
|
-
|
43
|
-
## Sorting in the Controller
|
44
|
-
|
45
|
-
To specify a default search sort field + order in the controller `index`:
|
46
|
-
|
47
|
-
```ruby
|
48
|
-
# app/controllers/posts_controller.rb
|
49
|
-
class PostsController < ActionController::Base
|
50
|
-
def index
|
51
|
-
@q = Post.ransack(params[:q])
|
52
|
-
@q.sorts = 'title asc' if @q.sorts.empty?
|
53
|
-
|
54
|
-
@posts = @q.result(distinct: true)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
```
|
58
|
-
|
59
|
-
Multiple sorts can be set by:
|
60
|
-
|
61
|
-
```ruby
|
62
|
-
# app/controllers/posts_controller.rb
|
63
|
-
class PostsController < ActionController::Base
|
64
|
-
def index
|
65
|
-
@q = Post.ransack(params[:q])
|
66
|
-
@q.sorts = ['title asc', 'created_at desc'] if @q.sorts.empty?
|
67
|
-
|
68
|
-
@posts = @q.result(distinct: true)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
```
|
@@ -1,282 +0,0 @@
|
|
1
|
-
---
|
2
|
-
title: Using Predicates
|
3
|
-
---
|
4
|
-
|
5
|
-
The primary method of searching in Ransack is by using what is known as *predicates*.
|
6
|
-
|
7
|
-
Predicates are used within Ransack search queries to determine what information to
|
8
|
-
match. For instance, the `cont` predicate will check to see if an attribute called
|
9
|
-
"first_name" contains a value using a wildcard query:
|
10
|
-
|
11
|
-
```ruby
|
12
|
-
>> User.ransack(first_name_cont: 'Rya').result.to_sql
|
13
|
-
=> SELECT "users".* FROM "users" WHERE ("users"."first_name" LIKE '%Rya%')
|
14
|
-
```
|
15
|
-
|
16
|
-
You can also combine predicates for OR queries:
|
17
|
-
```ruby
|
18
|
-
>> User.ransack(first_name_or_last_name_cont: 'Rya').result.to_sql
|
19
|
-
=> SELECT "users".* FROM "users" WHERE ("users"."first_name" LIKE '%Rya%'
|
20
|
-
OR "users"."last_name" LIKE '%Rya%')
|
21
|
-
```
|
22
|
-
|
23
|
-
The syntax for `OR` queries on an associated model is not immediately obvious, but makes sense. Assuming a `User` `has_one` `Account` and the `Account` has `attributes` `foo` and `bar`:
|
24
|
-
|
25
|
-
```ruby
|
26
|
-
>> User.ransack(account_foo_or_account_bar_cont: 'val').result.to_sql
|
27
|
-
=> SELECT "users".* FROM "users" INNER JOIN accounts ON accounts.user_id = users.id WHERE ("accounts.foo LIKE '%val%' OR accounts.bar LIKE '%val%')
|
28
|
-
```
|
29
|
-
|
30
|
-
Below is a list of the built-in predicates of Ransack and their opposites. You may already
|
31
|
-
be familiar with some of the predicates, as they also exist in the ARel library.
|
32
|
-
|
33
|
-
If you want to add your own, please
|
34
|
-
see the [[Custom-Predicates|Custom Predicates]] page.
|
35
|
-
|
36
|
-
**Please note:** any attempt to use a predicate for an attribute that does not exist will
|
37
|
-
*silently fail*. For instance, this will not work when there is no `name` attribute:
|
38
|
-
|
39
|
-
```ruby
|
40
|
-
>> User.ransack(name_cont: 'Rya').result.to_sql
|
41
|
-
=> "SELECT "users".* FROM "users"
|
42
|
-
```
|
43
|
-
|
44
|
-
## eq (equals)
|
45
|
-
|
46
|
-
The `eq` predicate returns all records where a field is *exactly* equal to a given value:
|
47
|
-
|
48
|
-
```ruby
|
49
|
-
>> User.ransack(first_name_eq: 'Ryan').result.to_sql
|
50
|
-
=> SELECT "users".* FROM "users" WHERE "users"."first_name" = 'Ryan'
|
51
|
-
```
|
52
|
-
|
53
|
-
**Opposite: `not_eq`**
|
54
|
-
|
55
|
-
## matches
|
56
|
-
|
57
|
-
The `matches` predicate returns all records where a field is like a given value:
|
58
|
-
|
59
|
-
```ruby
|
60
|
-
>> User.ransack(first_name_matches: 'Ryan').result.to_sql
|
61
|
-
=> SELECT "users".* FROM "users" WHERE ("users"."first_name" LIKE 'Ryan')
|
62
|
-
```
|
63
|
-
|
64
|
-
On Postgres, the case-insensitive ILIKE will be used.
|
65
|
-
|
66
|
-
**Opposite: `does_not_match`**
|
67
|
-
|
68
|
-
*Note: If you want to do wildcard matching, you may be looking for the `cont`/`not_cont`
|
69
|
-
predicates instead.*
|
70
|
-
|
71
|
-
## lt (less than)
|
72
|
-
|
73
|
-
The `lt` predicate returns all records where a field is less than a given value:
|
74
|
-
|
75
|
-
```ruby
|
76
|
-
>> User.ransack(age_lt: 25).result.to_sql
|
77
|
-
=> SELECT "users".* FROM "users" WHERE ("users"."age" < 25)
|
78
|
-
```
|
79
|
-
|
80
|
-
**Opposite: `gteq` (greater than or equal to)**
|
81
|
-
|
82
|
-
## lteq (less than or equal to)
|
83
|
-
|
84
|
-
The `lteq` predicate returns all records where a field is less than *or equal to* a given value:
|
85
|
-
|
86
|
-
```ruby
|
87
|
-
>> User.ransack(age_lteq: 25).result.to_sql
|
88
|
-
=> SELECT "users".* FROM "users" WHERE ("users"."age" <= 25)
|
89
|
-
```
|
90
|
-
|
91
|
-
**Opposite: `gt` (greater than)**
|
92
|
-
|
93
|
-
## in
|
94
|
-
|
95
|
-
The `in` predicate returns all records where a field is within a specified list:
|
96
|
-
|
97
|
-
```ruby
|
98
|
-
>> User.ransack(age_in: 20..25).result.to_sql
|
99
|
-
=> SELECT "users".* FROM "users" WHERE "users"."age" IN (20, 21, 22, 23, 24, 25)
|
100
|
-
```
|
101
|
-
|
102
|
-
It can also take an array:
|
103
|
-
|
104
|
-
```ruby
|
105
|
-
>> User.ransack(age_in: [20, 21, 22, 23, 24, 25]).result.to_sql
|
106
|
-
=> SELECT "users".* FROM "users" WHERE "users"."age" IN (20, 21, 22, 23, 24, 25)
|
107
|
-
```
|
108
|
-
|
109
|
-
**Opposite: `not_in`**
|
110
|
-
|
111
|
-
## cont
|
112
|
-
|
113
|
-
The `cont` predicate returns all records where a field contains a given value:
|
114
|
-
|
115
|
-
```ruby
|
116
|
-
>> User.ransack(first_name_cont: 'Rya').result.to_sql
|
117
|
-
=> SELECT "users".* FROM "users" WHERE ("users"."first_name" LIKE '%Rya%')
|
118
|
-
```
|
119
|
-
|
120
|
-
**Opposite: `not_cont`**
|
121
|
-
|
122
|
-
## cont_any (contains any)
|
123
|
-
|
124
|
-
The `cont_any` predicate returns all records where a field contains any of the given values:
|
125
|
-
|
126
|
-
```ruby
|
127
|
-
>> User.ransack(first_name_cont_any: %w(Rya Lis)).result.to_sql
|
128
|
-
=> SELECT "users".* FROM "users" WHERE (("users"."first_name" LIKE '%Rya%' OR "users"."first_name" LIKE '%Lis%'))
|
129
|
-
```
|
130
|
-
|
131
|
-
**Opposite: `not_cont_any`**
|
132
|
-
|
133
|
-
|
134
|
-
## cont_all (contains all)
|
135
|
-
|
136
|
-
The `cont_all` predicate returns all records where a field contains all of the given values:
|
137
|
-
|
138
|
-
```ruby
|
139
|
-
>> User.ransack(city_cont_all: %w(Grand Rapids)).result.to_sql
|
140
|
-
=> SELECT "users".* FROM "users" WHERE (("users"."city" LIKE '%Grand%' AND "users"."city" LIKE '%Rapids%'))
|
141
|
-
```
|
142
|
-
|
143
|
-
**Opposite: `not_cont_all`**
|
144
|
-
|
145
|
-
|
146
|
-
## i_cont
|
147
|
-
|
148
|
-
The `i_cont` case-insensitive predicate returns all records where a field contains a given value and ignores case:
|
149
|
-
|
150
|
-
```ruby
|
151
|
-
>> User.ransack(first_name_i_cont: 'Rya').result.to_sql
|
152
|
-
=> SELECT "users".* FROM "users" WHERE (LOWER("users"."first_name") LIKE '%rya%')
|
153
|
-
```
|
154
|
-
|
155
|
-
**Opposite: `not_i_cont`**
|
156
|
-
|
157
|
-
## i_cont_any
|
158
|
-
|
159
|
-
The `i_cont_any` case-insensitive predicate returns all records where a field contains any of the given values and ignores case:
|
160
|
-
|
161
|
-
```ruby
|
162
|
-
>> User.ransack(first_name_i_cont_any: %w(Rya Lis)).result.to_sql
|
163
|
-
=> SELECT "users".* FROM "users" WHERE ((LOWER("users"."first_name") LIKE '%rya%' OR LOWER("users"."first_name") LIKE '%lis%'))
|
164
|
-
```
|
165
|
-
|
166
|
-
**Opposite: `not_i_cont_any`**
|
167
|
-
|
168
|
-
|
169
|
-
## i_cont_all
|
170
|
-
|
171
|
-
The `i_cont_all` case-insensitive predicate returns all records where a field contains all of the given values and ignores case:
|
172
|
-
|
173
|
-
```ruby
|
174
|
-
>> User.ransack(city_i_cont_all: %w(Grand Rapids)).result.to_sql
|
175
|
-
=> SELECT "users".* FROM "users" WHERE ((LOWER("users"."city") LIKE '%grand%' AND LOWER("users"."city") LIKE '%rapids%'))
|
176
|
-
```
|
177
|
-
|
178
|
-
**Opposite: `not_i_cont_all`**
|
179
|
-
|
180
|
-
## start (starts with)
|
181
|
-
|
182
|
-
The `start` predicate returns all records where a field begins with a given value:
|
183
|
-
|
184
|
-
```ruby
|
185
|
-
>> User.ransack(first_name_start: 'Rya').result.to_sql
|
186
|
-
=> SELECT "users".* FROM "users" WHERE ("users"."first_name" LIKE 'Rya%')
|
187
|
-
```
|
188
|
-
|
189
|
-
**Opposite: `not_start`**
|
190
|
-
|
191
|
-
## end (ends with)
|
192
|
-
|
193
|
-
The `end` predicate returns all records where a field ends with a given value:
|
194
|
-
|
195
|
-
```ruby
|
196
|
-
>> User.ransack(first_name_end: 'yan').result.to_sql
|
197
|
-
=> SELECT "users".* FROM "users" WHERE ("users"."first_name" LIKE '%yan')
|
198
|
-
```
|
199
|
-
|
200
|
-
**Opposite: `not_end`**
|
201
|
-
|
202
|
-
## true
|
203
|
-
|
204
|
-
The `true` predicate returns all records where a field is true. The '1' indicates that
|
205
|
-
to Ransack that you indeed want to check the truthiness of this field. The other truthy
|
206
|
-
values are 'true', 'TRUE', 't' or 'T'.
|
207
|
-
|
208
|
-
```ruby
|
209
|
-
>> User.ransack(awesome_true: '1').result.to_sql
|
210
|
-
=> SELECT "users".* FROM "users" WHERE ("users"."awesome" = 't')
|
211
|
-
```
|
212
|
-
|
213
|
-
*Note: different database systems use different values to represent truth. In the above
|
214
|
-
example, we are using SQLite3.*
|
215
|
-
|
216
|
-
**Opposite: `not_true`**
|
217
|
-
|
218
|
-
## false
|
219
|
-
|
220
|
-
The `false` predicate returns all records where a field is false.
|
221
|
-
|
222
|
-
```ruby
|
223
|
-
>> User.ransack(awesome_false: '1').result.to_sql
|
224
|
-
=> SELECT "users".* FROM "users" WHERE ("users"."awesome" = 'f')
|
225
|
-
```
|
226
|
-
|
227
|
-
**Opposite: `not_false`**
|
228
|
-
|
229
|
-
*Note: the `false` predicate may be considered the opposite of the `true` predicate if the field does not contain `null` values. Otherwise, use `not_false`.*
|
230
|
-
|
231
|
-
## present
|
232
|
-
|
233
|
-
The `present` predicate returns all records where a field is present (not null and not a
|
234
|
-
blank string).
|
235
|
-
|
236
|
-
```ruby
|
237
|
-
>> User.ransack(first_name_present: '1').result.to_sql
|
238
|
-
=> SELECT "users".* FROM "users" WHERE (("users"."first_name" IS NOT NULL AND "users"."first_name" != ''))
|
239
|
-
```
|
240
|
-
|
241
|
-
**Opposite: `blank`**
|
242
|
-
|
243
|
-
## null
|
244
|
-
|
245
|
-
The `null` predicate returns all records where a field is null:
|
246
|
-
|
247
|
-
```ruby
|
248
|
-
>> User.ransack(first_name_null: 1).result.to_sql
|
249
|
-
=> SELECT "users".* FROM "users" WHERE "users"."first_name" IS NULL
|
250
|
-
```
|
251
|
-
|
252
|
-
**Opposite: `not_null`**
|
253
|
-
|
254
|
-
# URL parameter structure
|
255
|
-
|
256
|
-
The search parameters are passed to ransack as a hash. The URL representation of this hash uses the bracket notation: ```hash_name[key]=value```. The hash_name is the parameter which is defined in the controller, for instance ```q```. The key is the attribute and search predicate compound, for instance ```first_name_cont```, the value is the search parameter. When searching without using the search form helpers this URL structure needs to be created manually.
|
257
|
-
|
258
|
-
For example, the URL layout for searching and sorting users could looks like this:
|
259
|
-
|
260
|
-
```
|
261
|
-
/users.json?q[first_name_cont]=pete&q[last_name_cont]=jack&q[s]=created_at+desc
|
262
|
-
```
|
263
|
-
|
264
|
-
_Note that the sorting parameter ```s``` is nested within the ```q``` hash._
|
265
|
-
|
266
|
-
When using JavaScript to create such a URL, a matching jQuery request could look like this:
|
267
|
-
|
268
|
-
```javascript
|
269
|
-
$.ajax({
|
270
|
-
url: "/users.json",
|
271
|
-
data: {
|
272
|
-
q: {
|
273
|
-
first_name_cont: "pete",
|
274
|
-
last_name_cont: "jack",
|
275
|
-
s: "created_at desc"
|
276
|
-
}
|
277
|
-
},
|
278
|
-
success: function (data){
|
279
|
-
console.log(data);
|
280
|
-
}
|
281
|
-
});
|
282
|
-
```
|