ransack 1.3.0 → 1.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/.travis.yml +4 -1
- data/CHANGELOG.md +93 -0
- data/Gemfile +1 -1
- data/README.md +237 -71
- data/lib/ransack/adapters/active_record/3.0/context.rb +10 -0
- data/lib/ransack/adapters/active_record/3.1/context.rb +10 -0
- data/lib/ransack/adapters/active_record/base.rb +21 -10
- data/lib/ransack/adapters/active_record/compat.rb +1 -1
- data/lib/ransack/constants.rb +32 -5
- data/lib/ransack/context.rb +1 -1
- data/lib/ransack/locale/ro.yml +70 -0
- data/lib/ransack/search.rb +6 -3
- data/lib/ransack/translate.rb +88 -44
- data/lib/ransack/version.rb +1 -1
- data/spec/ransack/adapters/active_record/base_spec.rb +8 -0
- data/spec/ransack/adapters/active_record/context_spec.rb +27 -12
- data/spec/ransack/nodes/condition_spec.rb +10 -2
- data/spec/ransack/predicate_spec.rb +64 -0
- data/spec/ransack/search_spec.rb +23 -4
- data/spec/support/schema.rb +7 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0db00f7b95f26e2128972c34185a796559165d06
|
4
|
+
data.tar.gz: f1ae294b2bafceeb8a15429f19451cb52aadfe6a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 808bcea8000e9b72d236bed60f17fa66f44ed41b2d6eca83c64ced249f1f96346651312ca44dc0248cf90bc23ed7e8d092232846c6948f22c1f6847ff16079ac
|
7
|
+
data.tar.gz: 4826df4e710ce5022aa7231b77fc12e482832db3bcbef9e111c0bdcee7a5c172038be6087e867c77a249c5fad7c0f4918752f01144e3b4495c28b4039092b759
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
# Change Log
|
2
|
+
This change log was started in August 2014. All notable changes to this project
|
3
|
+
henceforth should be documented here.
|
4
|
+
|
5
|
+
## Version 1.4.0 - 2014-09-23
|
6
|
+
### Added
|
7
|
+
|
8
|
+
* Add support for Rails 4.2.0! Let us know if you encounter any issues.
|
9
|
+
|
10
|
+
*Xiang Li*
|
11
|
+
|
12
|
+
* Add `not_true` and `not_false` predicates and update the "Basic Searching"
|
13
|
+
wiki. Fixes #123, #353.
|
14
|
+
|
15
|
+
*Pedro Chambino*
|
16
|
+
|
17
|
+
* Add `ro.yml` Romanian translation file.
|
18
|
+
|
19
|
+
*Andreas Philippi*
|
20
|
+
|
21
|
+
* Add new documentation in the README explaining how to group queries by `OR`
|
22
|
+
instead of the default `AND` using the `m: 'or'` combinator.
|
23
|
+
|
24
|
+
* Add new documentation in the README and in the source code comments
|
25
|
+
explaining in detail how to handle whitelisting/authorization of
|
26
|
+
attributes, associations, sorts and scopes.
|
27
|
+
|
28
|
+
* Add new documentation in the README explaining in more detail how to use
|
29
|
+
scopes for searching with Ransack.
|
30
|
+
|
31
|
+
* Begin a CHANGELOG.
|
32
|
+
|
33
|
+
*Jon Atack*
|
34
|
+
|
35
|
+
### Fixed
|
36
|
+
|
37
|
+
* Fix singular/plural Active Record attribute translations.
|
38
|
+
|
39
|
+
*Andreas Philippi*
|
40
|
+
|
41
|
+
* Fix the params hash being modified by `Search.new` and the Ransack scope.
|
42
|
+
|
43
|
+
*Daniel Rikowski*
|
44
|
+
|
45
|
+
* Apply default scope conditions for association joins (fix for Rails 3).
|
46
|
+
|
47
|
+
Avoid selecting records from joins that would normally be filtered out
|
48
|
+
if they were selected from the base table. Only applies to Rails 3, as
|
49
|
+
this issue was fixed in Rails 4.
|
50
|
+
|
51
|
+
*Andrew Vit*
|
52
|
+
|
53
|
+
* Fix incoherent code examples in the README Associations section that
|
54
|
+
sometimes used `@q` and other times `@search`.
|
55
|
+
|
56
|
+
*Jon Atack*
|
57
|
+
|
58
|
+
### Changed
|
59
|
+
|
60
|
+
* Refactor Ransack::Translate.
|
61
|
+
|
62
|
+
* Rewrite much of the Ransack README documentation, including the
|
63
|
+
Associations section code examples and the Authorizations section detailing
|
64
|
+
how to whitelist attributes, associations, sorts and scopes.
|
65
|
+
|
66
|
+
*Jon Atack*
|
67
|
+
|
68
|
+
## Version 1.3.0 - 2014-08-23
|
69
|
+
### Added
|
70
|
+
|
71
|
+
* Add search scopes by popular demand. Using `ransackable_scopes`, users can
|
72
|
+
define whitelists for allowed model scopes on a parent table. Not yet
|
73
|
+
implemented for associated models' scopes; scopes must be defined on the
|
74
|
+
parent table.
|
75
|
+
|
76
|
+
*Gleb Mazovetskiy*, *Andrew Vit*, *Sven Schwyn*
|
77
|
+
|
78
|
+
* Add `JOINS` merging.
|
79
|
+
|
80
|
+
* Add `OR` grouping on base search.
|
81
|
+
|
82
|
+
* Allow authorizing/whitelisting attributes, associations, sorts and scopes.
|
83
|
+
|
84
|
+
* Improve boolean predicates’ handling of `false` values.
|
85
|
+
|
86
|
+
* Allow configuring Ransack to raise on instead of ignore unknown search
|
87
|
+
conditions.
|
88
|
+
|
89
|
+
* Allow passing blank values to search without crashing.
|
90
|
+
|
91
|
+
* Add wildcard escaping compatibility for SQL Server databases.
|
92
|
+
|
93
|
+
* Add various I18n translations.
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -9,7 +9,8 @@ Ransack is a rewrite of [MetaSearch]
|
|
9
9
|
(https://github.com/activerecord-hackery/meta_search)
|
10
10
|
created by [Ernie Miller](http://twitter.com/erniemiller)
|
11
11
|
and maintained by [Ryan Bigg](http://twitter.com/ryanbigg),
|
12
|
-
[Jon Atack](http://twitter.com/jonatack) and a great group of [contributors]
|
12
|
+
[Jon Atack](http://twitter.com/jonatack) and a great group of [contributors]
|
13
|
+
(https://github.com/activerecord-hackery/ransack/graphs/contributors).
|
13
14
|
While it supports many of the same features as MetaSearch, its underlying
|
14
15
|
implementation differs greatly from MetaSearch,
|
15
16
|
and backwards compatibility is not a design goal.
|
@@ -25,44 +26,25 @@ instead.
|
|
25
26
|
|
26
27
|
## Getting started
|
27
28
|
|
28
|
-
|
29
|
-
available in several flavors! Take your pick:
|
30
|
-
|
31
|
-
In your Gemfile, for the last officially released gem compatible with Rails
|
32
|
-
3.x, 4.0 and 4.1 (for Rails 4.2, use the dedicated `rails-4.2` branch described
|
33
|
-
below for now):
|
29
|
+
In your Gemfile, for the last officially released gem for Rails 3 and 4:
|
34
30
|
|
35
31
|
```ruby
|
36
32
|
gem 'ransack'
|
37
33
|
```
|
38
34
|
|
39
|
-
Or if you want to use the latest updates
|
35
|
+
Or if you want to use the latest updates (including Rails 4.2 compatibility):
|
40
36
|
|
41
37
|
```ruby
|
42
38
|
gem 'ransack', github: 'activerecord-hackery/ransack'
|
43
39
|
```
|
44
40
|
|
45
|
-
|
46
|
-
|
47
|
-
faster
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
Similarly, if you are using Rails 4.0, you may prefer the dedicated [Rails 4 branch](https://github.com/activerecord-hackery/ransack/tree/rails-4) for the
|
54
|
-
same reasons:
|
55
|
-
|
56
|
-
```ruby
|
57
|
-
gem 'ransack', github: 'activerecord-hackery/ransack', branch: 'rails-4'
|
58
|
-
```
|
59
|
-
|
60
|
-
Last but definitely not least, an experimental [Rails 4.2 branch](https://github.com/activerecord-hackery/ransack/tree/rails-4.2) is
|
61
|
-
available for those on the edge:
|
62
|
-
|
63
|
-
```ruby
|
64
|
-
gem 'ransack', github: 'activerecord-hackery/ransack', branch: 'rails-4.2'
|
65
|
-
```
|
41
|
+
The other branches (`rails-4`, `rails-4.1`, and `rails-4.2`) were each used for
|
42
|
+
running Ransack with the latest upcoming version of Rails at the time. They are
|
43
|
+
lighter and somewhat faster-running because they do not have to support previous
|
44
|
+
versions of Rails and Active Record. However, once support for that version of
|
45
|
+
Rails is merged into Ransack master, the branches are no longer actively
|
46
|
+
maintained with the latest fixes and additions to Ransack -- unless the
|
47
|
+
community submits pull requests to maintain them, and you are welcome to do so!
|
66
48
|
|
67
49
|
## Usage
|
68
50
|
|
@@ -87,16 +69,18 @@ If you're coming from MetaSearch, things to note:
|
|
87
69
|
3. Common ActiveRecord::Relation methods are no longer delegated by the
|
88
70
|
search object. Instead, you will get your search results (an
|
89
71
|
ActiveRecord::Relation in the case of the ActiveRecord adapter) via a call to
|
90
|
-
`Search#result`.
|
91
|
-
|
92
|
-
|
72
|
+
`Search#result`.
|
73
|
+
|
74
|
+
4. If passed `distinct: true`, `result` will generate a `SELECT DISTINCT` to
|
75
|
+
avoid returning duplicate rows, even if conditions on a join would otherwise
|
76
|
+
result in some.
|
93
77
|
|
94
78
|
Please note that for many databases, a sort on an associated table's columns
|
95
|
-
|
79
|
+
may result in invalid SQL with `distinct: true` -- in those cases, you're on
|
96
80
|
your own, and will need to modify the result as needed to allow these queries
|
97
|
-
to work.
|
98
|
-
|
99
|
-
|
81
|
+
to work. If `distinct: true` is causing you problems, another way to remove
|
82
|
+
duplicates is to call `#to_a.uniq` on your collection instead (see the next
|
83
|
+
section below).
|
100
84
|
|
101
85
|
####In your controller
|
102
86
|
|
@@ -113,6 +97,8 @@ this example, with preloading each Person's Articles and pagination):
|
|
113
97
|
def index
|
114
98
|
@q = Person.search(params[:q])
|
115
99
|
@people = @q.result.includes(:articles).page(params[:page])
|
100
|
+
# or use `to_a.uniq` to remove duplicates (can also be done in the view):
|
101
|
+
@people = @q.result.includes(:articles).page(params[:page]).to_a.uniq
|
116
102
|
end
|
117
103
|
```
|
118
104
|
|
@@ -126,10 +112,19 @@ which are defined in
|
|
126
112
|
|
127
113
|
```erb
|
128
114
|
<%= search_form_for @q do |f| %>
|
115
|
+
|
116
|
+
# Search if the name field contains...
|
129
117
|
<%= f.label :name_cont %>
|
130
118
|
<%= f.search_field :name_cont %>
|
119
|
+
|
120
|
+
# Search if an associated articles.title starts with...
|
131
121
|
<%= f.label :articles_title_start %>
|
132
122
|
<%= f.search_field :articles_title_start %>
|
123
|
+
|
124
|
+
# Attributes may be chained. Search multiple attributes for one value...
|
125
|
+
<%= f.label :name_or_description_or_email_or_articles_title_cont %>
|
126
|
+
<%= f.search_field :name_or_description_or_email_or_articles_title_cont %>
|
127
|
+
|
133
128
|
<%= f.submit %>
|
134
129
|
<% end %>
|
135
130
|
```
|
@@ -210,9 +205,10 @@ Article.search(params[:q])
|
|
210
205
|
Article.ransack(params[:q])
|
211
206
|
```
|
212
207
|
|
213
|
-
###
|
208
|
+
### Associations
|
214
209
|
|
215
|
-
You can easily use Ransack to search in
|
210
|
+
You can easily use Ransack to search for objects in `has_many` and `belongs_to`
|
211
|
+
associations.
|
216
212
|
|
217
213
|
Given you have these associations ...
|
218
214
|
|
@@ -220,7 +216,7 @@ Given you have these associations ...
|
|
220
216
|
class Employee < ActiveRecord::Base
|
221
217
|
belongs_to :supervisor
|
222
218
|
|
223
|
-
# has
|
219
|
+
# has attributes first_name:string and last_name:string
|
224
220
|
end
|
225
221
|
|
226
222
|
class Department < ActiveRecord::Base
|
@@ -242,8 +238,8 @@ end
|
|
242
238
|
```ruby
|
243
239
|
class SupervisorsController < ApplicationController
|
244
240
|
def index
|
245
|
-
@
|
246
|
-
@supervisors = @
|
241
|
+
@q = Supervisor.search(params[:q])
|
242
|
+
@supervisors = @q.result.includes(:department, :employees)
|
247
243
|
end
|
248
244
|
end
|
249
245
|
```
|
@@ -251,15 +247,15 @@ end
|
|
251
247
|
... you might set up your form like this ...
|
252
248
|
|
253
249
|
```erb
|
254
|
-
<%= search_form_for @
|
250
|
+
<%= search_form_for @q do |f| %>
|
255
251
|
<%= f.label :last_name_cont %>
|
256
252
|
<%= f.search_field :last_name_cont %>
|
257
253
|
|
258
254
|
<%= f.label :department_title_cont %>
|
259
255
|
<%= f.search_field :department_title_cont %>
|
260
256
|
|
261
|
-
<%= f.label :
|
262
|
-
<%= f.search_field :
|
257
|
+
<%= f.label :employees_first_name_or_employees_last_name_cont %>
|
258
|
+
<%= f.search_field :employees_first_name_or_employees_last_name_cont %>
|
263
259
|
|
264
260
|
<%= f.submit "search" %>
|
265
261
|
<% end %>
|
@@ -280,50 +276,220 @@ information about `ransacker` methods can be found [here in the wiki]
|
|
280
276
|
(https://github.com/activerecord-hackery/ransack/wiki/Using-Ransackers).
|
281
277
|
Feel free to contribute working `ransacker` code examples to the wiki!
|
282
278
|
|
283
|
-
###
|
279
|
+
### Authorization (whitelisting/blacklisting)
|
284
280
|
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
281
|
+
By default, searching and sorting are authorized on any column of your model
|
282
|
+
and no class methods/scopes are whitelisted.
|
283
|
+
|
284
|
+
Ransack adds four methods to `ActiveRecord::Base` that you can redefine as
|
285
|
+
class methods in your models to apply selective authorization:
|
286
|
+
`ransackable_attributes`, `ransackable_associations`, `ransackable_scopes` and
|
287
|
+
`ransortable_attributes`.
|
288
|
+
|
289
|
+
Here is how these four methods are implemented in Ransack:
|
289
290
|
|
290
291
|
```ruby
|
291
|
-
|
292
|
+
def ransackable_attributes(auth_object = nil)
|
293
|
+
# By default returns all column names and any defined ransackers as an array
|
294
|
+
# of strings. For overriding with a whitelist array of strings.
|
295
|
+
column_names + _ransackers.keys
|
296
|
+
end
|
292
297
|
|
293
|
-
|
298
|
+
def ransackable_associations(auth_object = nil)
|
299
|
+
# By default returns the names of all associations as an array of strings.
|
300
|
+
# For overriding with a whitelist array of strings.
|
301
|
+
reflect_on_all_associations.map { |a| a.name.to_s }
|
302
|
+
end
|
294
303
|
|
295
|
-
|
304
|
+
def ransortable_attributes(auth_object = nil)
|
305
|
+
# By default returns the names of all attributes for sorting as an array of
|
306
|
+
# strings. For overriding with a whitelist array of strings.
|
307
|
+
ransackable_attributes(auth_object)
|
308
|
+
end
|
309
|
+
|
310
|
+
def ransackable_scopes(auth_object = nil)
|
311
|
+
# By default returns an empty array, i.e. no class methods/scopes
|
312
|
+
# are authorized. For overriding with a whitelist array of *symbols*.
|
313
|
+
[]
|
314
|
+
end
|
296
315
|
```
|
297
316
|
|
298
|
-
|
317
|
+
Any values not returned from these methods will be ignored by Ransack, i.e.
|
318
|
+
they are not authorized.
|
299
319
|
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
320
|
+
All four methods can receive a single optional parameter, `auth_object`. When
|
321
|
+
you call the search or ransack method on your model, you can provide a value
|
322
|
+
for an `auth_object` key in the options hash which can be used by your own
|
323
|
+
overridden methods.
|
304
324
|
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
325
|
+
Here is an example that puts all this together, adapted from
|
326
|
+
[this blog post by Ernie Miller]
|
327
|
+
(http://erniemiller.org/2012/05/11/why-your-ruby-class-macros-might-suck-mine-did/).
|
328
|
+
In an `Article` model, add the following `ransackable_attributes` class method
|
329
|
+
(preferably private):
|
330
|
+
```ruby
|
331
|
+
# article.rb
|
332
|
+
class Article < ActiveRecord::Base
|
333
|
+
|
334
|
+
private
|
335
|
+
|
336
|
+
def self.ransackable_attributes(auth_object = nil)
|
337
|
+
if auth_object == :admin
|
338
|
+
# whitelist all attributes for admin
|
339
|
+
super
|
340
|
+
else
|
341
|
+
# whitelist only the title and body attributes for other users
|
342
|
+
super & %w(title body)
|
343
|
+
end
|
344
|
+
end
|
345
|
+
end
|
346
|
+
```
|
347
|
+
Here is example code for the `articles_controller`:
|
348
|
+
```ruby
|
349
|
+
# articles_controller.rb
|
350
|
+
class ArticlesController < ApplicationController
|
309
351
|
|
310
|
-
|
311
|
-
|
312
|
-
|
352
|
+
def index
|
353
|
+
@q = Article.search(params[:q], auth_object: set_ransack_auth_object)
|
354
|
+
@articles = @q.result
|
355
|
+
end
|
356
|
+
|
357
|
+
private
|
313
358
|
|
359
|
+
def set_ransack_auth_object
|
360
|
+
current_user.admin? ? :admin : nil
|
361
|
+
end
|
362
|
+
end
|
314
363
|
```
|
315
|
-
|
316
|
-
```
|
364
|
+
Trying it out in `rails console`:
|
365
|
+
```ruby
|
366
|
+
> Article
|
367
|
+
=> Article(id: integer, person_id: integer, title: string, body: text)
|
368
|
+
|
369
|
+
> Article.ransackable_attributes
|
370
|
+
=> ["title", "body"]
|
371
|
+
|
372
|
+
> Article.ransackable_attributes(:admin)
|
373
|
+
=> ["id", "person_id", "title", "body"]
|
317
374
|
|
318
|
-
|
375
|
+
> Article.search(id_eq: 1).result.to_sql
|
376
|
+
=> SELECT "articles".* FROM "articles" # Note that search param was ignored!
|
319
377
|
|
320
|
-
|
321
|
-
|
322
|
-
will be applied for matching `true` values, or for given values if the scope
|
323
|
-
accepts a value:
|
378
|
+
> Article.search({ id_eq: 1 }, { auth_object: nil }).result.to_sql
|
379
|
+
=> SELECT "articles".* FROM "articles" # Search param still ignored!
|
324
380
|
|
381
|
+
> Article.search({ id_eq: 1 }, { auth_object: :admin }).result.to_sql
|
382
|
+
=> SELECT "articles".* FROM "articles" WHERE "articles"."id" = 1
|
325
383
|
```
|
384
|
+
That's it! Now you know how to whitelist/blacklist various elements in Ransack.
|
385
|
+
|
386
|
+
### Using Scopes/Class Methods
|
387
|
+
|
388
|
+
Continuing on from the preceding section, searching by scopes requires defining
|
389
|
+
a whitelist of `ransackable_scopes` on the model class. The whitelist should be
|
390
|
+
an array of *symbols*. By default, all class methods (e.g. scopes) are ignored.
|
391
|
+
Scopes will be applied for matching `true` values, or for given values if the
|
392
|
+
scope accepts a value:
|
393
|
+
|
394
|
+
```ruby
|
395
|
+
class Employee < ActiveRecord::Base
|
396
|
+
scope :active, ->(boolean = true) { (where active: boolean) }
|
397
|
+
scope :salary_gt, ->(amount) { where('salary > ?', amount) }
|
398
|
+
|
399
|
+
# Scopes are just syntactical sugar for class methods, which may also be used:
|
400
|
+
|
401
|
+
def self.hired_since(date)
|
402
|
+
where('start_date >= ?', date)
|
403
|
+
end
|
404
|
+
|
405
|
+
private
|
406
|
+
|
407
|
+
def self.ransackable_scopes(auth_object = nil)
|
408
|
+
if auth_object.try(:admin?)
|
409
|
+
# allow admin users access to all three methods
|
410
|
+
%i(active hired_since salary_gt)
|
411
|
+
else
|
412
|
+
# allow other users to search on active and hired_since only
|
413
|
+
%i(active hired_since)
|
414
|
+
end
|
415
|
+
end
|
416
|
+
end
|
417
|
+
|
326
418
|
Employee.search({ active: true, hired_since: '2013-01-01' })
|
419
|
+
|
420
|
+
Employee.search({ salary_gt: 100_000 }, { auth_object: current_user })
|
421
|
+
```
|
422
|
+
|
423
|
+
### Grouping queries by OR instead of AND
|
424
|
+
|
425
|
+
The default `AND` grouping can be changed to `OR` by adding `m: 'or'` to the
|
426
|
+
query hash.
|
427
|
+
|
428
|
+
You can easily try it in your controller code by changing `params[:q]` in the
|
429
|
+
`index` action to `params[:q].try(:merge, m: 'or')` as follows:
|
430
|
+
|
431
|
+
```ruby
|
432
|
+
def index
|
433
|
+
@q = Artist.search(params[:q].try(:merge, m: 'or'))
|
434
|
+
@artists = @q.result
|
435
|
+
end
|
436
|
+
```
|
437
|
+
Normally, if you wanted users to be able to toggle between `AND` and `OR`
|
438
|
+
query grouping, you would probably set up your search form so that `m` was in
|
439
|
+
the URL params hash, but here we assigned `m` manually just to try it out
|
440
|
+
quickly.
|
441
|
+
|
442
|
+
Alternatively, trying it in the Rails console:
|
443
|
+
|
444
|
+
```ruby
|
445
|
+
artists = Artist.search(name_cont: 'foo', style_cont: 'bar', m: 'or')
|
446
|
+
=> Ransack::Search<class: Artist, base: Grouping <conditions: [
|
447
|
+
Condition <attributes: ["name"], predicate: cont, values: ["foo"]>,
|
448
|
+
Condition <attributes: ["style"], predicate: cont, values: ["bar"]>
|
449
|
+
], combinator: or>>
|
450
|
+
|
451
|
+
artists.result.to_sql
|
452
|
+
=> "SELECT \"artists\".* FROM \"artists\"
|
453
|
+
WHERE ((\"artists\".\"name\" ILIKE '%foo%'
|
454
|
+
OR \"artists\".\"style\" ILIKE '%bar%'))"
|
455
|
+
```
|
456
|
+
|
457
|
+
The combinator becomes `or` instead of the default `and`, and the SQL query
|
458
|
+
becomes `WHERE...OR` instead of `WHERE...AND`.
|
459
|
+
|
460
|
+
This works with associations as well. Imagine an Artist model that has many
|
461
|
+
Memberships, and many Musicians through Memberships:
|
462
|
+
|
463
|
+
```ruby
|
464
|
+
artists = Artist.search(name_cont: 'foo', musicians_email_cont: 'bar', m: 'or')
|
465
|
+
=> Ransack::Search<class: Artist, base: Grouping <conditions: [
|
466
|
+
Condition <attributes: ["name"], predicate: cont, values: ["foo"]>,
|
467
|
+
Condition <attributes: ["musicians_email"], predicate: cont, values: ["bar"]>
|
468
|
+
], combinator: or>>
|
469
|
+
|
470
|
+
artists.result.to_sql
|
471
|
+
=> "SELECT \"artists\".* FROM \"artists\"
|
472
|
+
LEFT OUTER JOIN \"memberships\"
|
473
|
+
ON \"memberships\".\"artist_id\" = \"artists\".\"id\"
|
474
|
+
LEFT OUTER JOIN \"musicians\"
|
475
|
+
ON \"musicians\".\"id\" = \"memberships\".\"musician_id\"
|
476
|
+
WHERE ((\"artists\".\"name\" ILIKE '%foo%'
|
477
|
+
OR \"musicians\".\"email\" ILIKE '%bar%'))"
|
478
|
+
```
|
479
|
+
|
480
|
+
### Using SimpleForm
|
481
|
+
|
482
|
+
If you want to combine form builders of ransack and SimpleForm, just set the
|
483
|
+
RANSACK_FORM_BUILDER environment variable before Rails started, e.g. in
|
484
|
+
``config/application.rb`` before ``require 'rails/all'`` and of course use
|
485
|
+
``gem 'simple_form'`` in your ``Gemfile``:
|
486
|
+
|
487
|
+
```ruby
|
488
|
+
require File.expand_path('../boot', __FILE__)
|
489
|
+
|
490
|
+
ENV['RANSACK_FORM_BUILDER'] = '::SimpleForm::FormBuilder'
|
491
|
+
|
492
|
+
require 'rails/all'
|
327
493
|
```
|
328
494
|
|
329
495
|
### I18n
|