ransack 1.2.2 → 1.2.3
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 +2 -0
- data/Gemfile +2 -2
- data/README.md +45 -28
- data/lib/ransack/adapters/active_record/context.rb +13 -14
- data/lib/ransack/helpers/form_builder.rb +2 -6
- data/lib/ransack/helpers/form_helper.rb +5 -2
- data/lib/ransack/locale/cs.yml +70 -0
- data/lib/ransack/locale/es.yml +70 -0
- data/lib/ransack/locale/fr.yml +70 -0
- data/lib/ransack/locale/zh.yml +1 -1
- data/lib/ransack/search.rb +1 -1
- data/lib/ransack/version.rb +1 -1
- data/spec/ransack/adapters/active_record/base_spec.rb +33 -32
- data/spec/ransack/dependencies_spec.rb +1 -1
- data/spec/ransack/helpers/form_helper_spec.rb +83 -33
- data/spec/ransack/search_spec.rb +52 -35
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5aa40c542dc092988fc46513f6f30ea6ccef3ca6
|
4
|
+
data.tar.gz: 22a6a9efcafac2879f41cbaa5f90fdac6d9d85f8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f31218e27e2a9aae5cd2bbaf5588627872338c4f5fcb6babb8f2dc4b81abf0c645ea3edb84ee514aaa2d946621c54cbba835400b9389ad8f61bd68356e6c2890
|
7
|
+
data.tar.gz: 117c2bf5a8f01b1461a03073c335dcb544ccf6b09187517123c90235efac7465cf4c9bde21d6f3e75880e3a032b0bc9b4e04a9c006cb7a15111fbadfd6486ed7
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,42 +1,52 @@
|
|
1
1
|
# Ransack
|
2
2
|
|
3
|
-
[]
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
3
|
+
[]
|
4
|
+
(https://travis-ci.org/activerecord-hackery/ransack)
|
5
|
+
[]
|
6
|
+
(http://badge.fury.io/rb/ransack)
|
7
|
+
|
8
|
+
Ransack is a rewrite of [MetaSearch]
|
9
|
+
(https://github.com/activerecord-hackery/meta_search)
|
10
|
+
created by [Ernie Miller](http://twitter.com/erniemiller)
|
11
|
+
and maintained by [Ryan Bigg](http://twitter.com/ryanbigg),
|
12
|
+
[Jon Atack](http://twitter.com/jonatack) and a great group of [contributors](https://github.com/activerecord-hackery/ransack/graphs/contributors).
|
13
|
+
While it supports many of the same features as MetaSearch, its underlying
|
14
|
+
implementation differs greatly from MetaSearch,
|
15
|
+
and _backwards compatibility is not a design goal._
|
16
|
+
|
17
|
+
Ransack enables the creation of both simple and
|
18
|
+
[advanced](http://ransack-demo.herokuapp.com/users/advanced_search)
|
19
|
+
search forms against your application's models (demo source code
|
20
|
+
[here](https://github.com/activerecord-hackery/ransack_demo)).
|
21
|
+
If you're looking for something that simplifies query generation at the model
|
22
|
+
or controller layer, you're probably not looking for Ransack (or MetaSearch,
|
23
|
+
for that matter). Try [Squeel](https://github.com/activerecord-hackery/squeel)
|
24
|
+
instead.
|
14
25
|
|
15
26
|
## Getting started
|
16
27
|
|
17
28
|
In your Gemfile:
|
18
29
|
|
19
30
|
```ruby
|
20
|
-
gem "ransack" # Last officially released gem (compatible Rails 3
|
31
|
+
gem "ransack" # Last officially released gem (compatible with Rails 3, 4.0 and 4.1!)
|
21
32
|
```
|
22
33
|
|
23
|
-
Or if you want to use the latest updates
|
34
|
+
Or if you want to use the latest updates on the master branch:
|
24
35
|
|
25
36
|
```ruby
|
26
|
-
gem "ransack", github: "activerecord-hackery/ransack" # Track git repo
|
37
|
+
gem "ransack", github: "activerecord-hackery/ransack" # Track git repo
|
27
38
|
```
|
28
39
|
|
29
|
-
If you are on Rails 4.0, you may prefer to use the
|
40
|
+
If you are on Rails 4.1 (or 4.2.0.alpha or master), you may prefer to use the dedicated [Rails 4.1 branch](https://github.com/activerecord-hackery/ransack/tree/rails-4.1) which contains the latest updates, supports only 4.1 and up, and is lighter and somewhat faster:
|
30
41
|
|
31
42
|
```ruby
|
32
|
-
gem "ransack", github: "activerecord-hackery/ransack", branch: "rails-4"
|
43
|
+
gem "ransack", github: "activerecord-hackery/ransack", branch: "rails-4.1"
|
33
44
|
```
|
34
45
|
|
35
|
-
|
46
|
+
Similarly, if you are on Rails 4.0, you may prefer to use the dedicated [Rails 4 branch](https://github.com/activerecord-hackery/ransack/tree/rails-4) for the same reasons:
|
36
47
|
|
37
48
|
```ruby
|
38
|
-
gem "ransack", github: "activerecord-hackery/ransack", branch: "rails-4
|
39
|
-
gem "polyamorous", github: "activerecord-hackery/polyamorous"
|
49
|
+
gem "ransack", github: "activerecord-hackery/ransack", branch: "rails-4"
|
40
50
|
```
|
41
51
|
|
42
52
|
## Usage
|
@@ -95,6 +105,17 @@ In your view:
|
|
95
105
|
`cont` (contains) and `start` (starts with) are just two of the available search predicates.
|
96
106
|
See [Constants](https://github.com/activerecord-hackery/ransack/blob/master/lib/ransack/constants.rb) for a full list and the [wiki](https://github.com/activerecord-hackery/ransack/wiki/Basic-Searching) for more description.
|
97
107
|
|
108
|
+
You can also set the `search_form_for` answer format, like this:
|
109
|
+
```erb
|
110
|
+
<%= search_form_for(@q, format: :pdf) do |f| %>
|
111
|
+
...
|
112
|
+
<% end %>
|
113
|
+
|
114
|
+
<%= search_form_for(@q, format: :json) do |f| %>
|
115
|
+
...
|
116
|
+
<% end %>
|
117
|
+
```
|
118
|
+
|
98
119
|
### Advanced Mode
|
99
120
|
|
100
121
|
"Advanced" searches (ab)use Rails' nested attributes functionality in order to generate
|
@@ -129,7 +150,7 @@ end
|
|
129
150
|
html: { method: :post } do |f| %>
|
130
151
|
```
|
131
152
|
|
132
|
-
Once you've done so, you can make use of the helpers in Ransack::Helpers::FormBuilder to
|
153
|
+
Once you've done so, you can make use of the helpers in [Ransack::Helpers::FormBuilder](lib/ransack/helpers/form_builder.rb) to
|
133
154
|
construct much more complex search forms, such as the one on the
|
134
155
|
[demo page](http://ransack-demo.heroku.com) (source code [here](https://github.com/activerecord-hackery/ransack_demo)).
|
135
156
|
|
@@ -137,7 +158,7 @@ construct much more complex search forms, such as the one on the
|
|
137
158
|
|
138
159
|
Ransack will try to to make `#search` available in your models, but in the case that `#search` has already been defined, you can use `#ransack` instead. For example the following would be equivalent:
|
139
160
|
|
140
|
-
```
|
161
|
+
```ruby
|
141
162
|
Article.search(params[:q])
|
142
163
|
Article.ransack(params[:q])
|
143
164
|
```
|
@@ -210,18 +231,14 @@ require 'rails/all'
|
|
210
231
|
|
211
232
|
## I18n
|
212
233
|
|
213
|
-
|
214
|
-
|
215
|
-
http://www.localeapp.com/projects/2999
|
234
|
+
Ransack translation files are available in [Ransack::Locale](lib/ransack/locale). You may also be interested in one of the many translations for Ransack available at http://www.localeapp.com/projects/2999.
|
216
235
|
|
217
236
|
## Contributions
|
218
237
|
|
219
238
|
To support the project:
|
220
239
|
|
221
|
-
* Use Ransack in your apps, and let us know if you encounter anything that's broken or missing.
|
222
|
-
|
223
|
-
* Spread the word on Twitter, Facebook, and elsewhere if Ransack's been useful to you. The more
|
224
|
-
people who are using the project, the quicker we can find and fix bugs!
|
240
|
+
* Use Ransack in your apps, and let us know if you encounter anything that's broken or missing. A failing spec is awesome. A pull request with tests that pass is even better! Before filing an issue or pull request, be sure to read the [Contributing Guide](CONTRIBUTING.md).
|
241
|
+
* Spread the word on Twitter, Facebook, and elsewhere if Ransack's been useful to you. The more people who are using the project, the quicker we can find and fix bugs!
|
225
242
|
|
226
243
|
## Copyright
|
227
244
|
|
@@ -156,25 +156,20 @@ module Ransack
|
|
156
156
|
join_dependency.alias_tracker.aliases[join.left.name.downcase] = 1
|
157
157
|
end
|
158
158
|
|
159
|
-
if ::ActiveRecord::VERSION::STRING >=
|
159
|
+
if ::ActiveRecord::VERSION::STRING >= '4.1'
|
160
160
|
join_dependency
|
161
161
|
else
|
162
162
|
join_dependency.graft(*stashed_association_joins)
|
163
163
|
end
|
164
164
|
end
|
165
165
|
|
166
|
-
if ::ActiveRecord::VERSION::STRING >=
|
166
|
+
if ::ActiveRecord::VERSION::STRING >= '4.1'
|
167
167
|
|
168
168
|
def build_or_find_association(name, parent = @base, klass = nil)
|
169
|
-
|
170
|
-
|
171
|
-
else
|
172
|
-
@join_dependency.join_associations
|
173
|
-
end
|
174
|
-
|
175
|
-
found_association = list.detect do |assoc|
|
169
|
+
found_association = @join_dependency.join_root.children
|
170
|
+
.detect do |assoc|
|
176
171
|
assoc.reflection.name == name &&
|
177
|
-
@associations_pot[assoc] == parent &&
|
172
|
+
(@associations_pot.nil? || @associations_pot[assoc] == parent) &&
|
178
173
|
(!klass || assoc.reflection.klass == klass)
|
179
174
|
end
|
180
175
|
|
@@ -199,7 +194,6 @@ module Ransack
|
|
199
194
|
# Leverage the stashed association functionality in AR
|
200
195
|
@object = @object.joins(jd)
|
201
196
|
end
|
202
|
-
|
203
197
|
found_association
|
204
198
|
end
|
205
199
|
|
@@ -207,6 +201,7 @@ module Ransack
|
|
207
201
|
@associations_pot ||= {}
|
208
202
|
@associations_pot[assoc] = parent
|
209
203
|
end
|
204
|
+
|
210
205
|
else
|
211
206
|
|
212
207
|
def build_or_find_association(name, parent = @base, klass = nil)
|
@@ -217,16 +212,20 @@ module Ransack
|
|
217
212
|
(!klass || assoc.reflection.klass == klass)
|
218
213
|
end
|
219
214
|
unless found_association
|
220
|
-
@join_dependency.send(
|
221
|
-
|
215
|
+
@join_dependency.send(
|
216
|
+
:build,
|
217
|
+
Polyamorous::Join.new(name, @join_type, klass),
|
218
|
+
parent
|
219
|
+
)
|
222
220
|
found_association = @join_dependency.join_associations.last
|
223
221
|
# Leverage the stashed association functionality in AR
|
224
222
|
@object = @object.joins(found_association)
|
225
223
|
end
|
226
|
-
|
227
224
|
found_association
|
228
225
|
end
|
226
|
+
|
229
227
|
end
|
228
|
+
|
230
229
|
end
|
231
230
|
end
|
232
231
|
end
|
@@ -107,13 +107,9 @@ module Ransack
|
|
107
107
|
|
108
108
|
def predicate_select(options = {}, html_options = {})
|
109
109
|
options[:compounds] = true if options[:compounds].nil?
|
110
|
-
|
111
|
-
default = options.delete(:default) || 'cont'
|
112
|
-
else
|
113
|
-
default = options.delete(:default) || 'eq'
|
114
|
-
end
|
110
|
+
default = options.delete(:default) || 'cont'
|
115
111
|
|
116
|
-
keys = options[:compounds] ? Predicate.names :
|
112
|
+
keys = options[:compounds] ? Predicate.names :
|
117
113
|
Predicate.names.reject { |k| k.match(/_(any|all)$/) }
|
118
114
|
if only = options[:only]
|
119
115
|
if only.respond_to? :call
|
@@ -5,11 +5,14 @@ module Ransack
|
|
5
5
|
def search_form_for(record, options = {}, &proc)
|
6
6
|
if record.is_a?(Ransack::Search)
|
7
7
|
search = record
|
8
|
-
options[:url] ||= polymorphic_path(
|
8
|
+
options[:url] ||= polymorphic_path(
|
9
|
+
search.klass, format: options.delete(:format)
|
10
|
+
)
|
9
11
|
elsif record.is_a?(Array) &&
|
10
12
|
(search = record.detect { |o| o.is_a?(Ransack::Search) })
|
11
13
|
options[:url] ||= polymorphic_path(
|
12
|
-
record.map { |o| o.is_a?(Ransack::Search) ? o.klass : o }
|
14
|
+
record.map { |o| o.is_a?(Ransack::Search) ? o.klass : o },
|
15
|
+
format: options.delete(:format)
|
13
16
|
)
|
14
17
|
else
|
15
18
|
raise ArgumentError,
|
@@ -0,0 +1,70 @@
|
|
1
|
+
cs:
|
2
|
+
ransack:
|
3
|
+
search: "vyhledávání"
|
4
|
+
predicate: "predikát"
|
5
|
+
and: "a"
|
6
|
+
or: "nebo"
|
7
|
+
any: "kteroukoliv"
|
8
|
+
all: "každou"
|
9
|
+
combinator: "kombinátor"
|
10
|
+
attribute: "atribut"
|
11
|
+
value: "hodnota"
|
12
|
+
condition: "podmínka"
|
13
|
+
sort: "řazení"
|
14
|
+
asc: "vzestupné"
|
15
|
+
desc: "sestupné"
|
16
|
+
predicates:
|
17
|
+
eq: "rovno"
|
18
|
+
eq_any: "rovno kterékoliv"
|
19
|
+
eq_all: "rovno všem"
|
20
|
+
not_eq: "nerovno"
|
21
|
+
not_eq_any: "nerovno kterékoliv"
|
22
|
+
not_eq_all: "nerovno všem"
|
23
|
+
matches: "odpovídá"
|
24
|
+
matches_any: "odpovídá kterékoliv"
|
25
|
+
matches_all: "odpovídá všem"
|
26
|
+
does_not_match: "neodpovídá"
|
27
|
+
does_not_match_any: "neodpovídá kterékoliv"
|
28
|
+
does_not_match_all: "neodpovídá všem"
|
29
|
+
lt: "menší než"
|
30
|
+
lt_any: "menší než kterákoliv"
|
31
|
+
lt_all: "menší než všechny"
|
32
|
+
lteq: "menší nebo rovno než"
|
33
|
+
lteq_any: "menší nebo rovno než kterákoliv"
|
34
|
+
lteq_all: "menší nebo rovno než všechny"
|
35
|
+
gt: "větší než"
|
36
|
+
gt_any: "větší než kterákoliv"
|
37
|
+
gt_all: "větší než všechny"
|
38
|
+
gteq: "větší nebo rovno než"
|
39
|
+
gteq_any: "větší nebo rovno než kterákoliv"
|
40
|
+
gteq_all: "větší nebo rovno než všechny"
|
41
|
+
in: "v"
|
42
|
+
in_any: "v kterékoliv"
|
43
|
+
in_all: "ve všech"
|
44
|
+
not_in: "není v"
|
45
|
+
not_in_any: "není v kterékoliv"
|
46
|
+
not_in_all: "není ve všech"
|
47
|
+
cont: "obsahuje"
|
48
|
+
cont_any: "obsahuje kterékoliv"
|
49
|
+
cont_all: "obsahuje všechny"
|
50
|
+
not_cont: "neobsahuje"
|
51
|
+
not_cont_any: "neobsahuje kteroukoliv"
|
52
|
+
not_cont_all: "neobsahuje všechny"
|
53
|
+
start: "začíná s"
|
54
|
+
start_any: "začíná s kteroukoliv"
|
55
|
+
start_all: "začíná se všemi"
|
56
|
+
not_start: "nezačíná s"
|
57
|
+
not_start_any: "nezačíná s kteroukoliv"
|
58
|
+
not_start_all: "nezačíná se všemi"
|
59
|
+
end: "končí s"
|
60
|
+
end_any: "končí s kteroukoliv"
|
61
|
+
end_all: "končí se všemi"
|
62
|
+
not_end: "nekončí s"
|
63
|
+
not_end_any: "nekončí s kteroukoliv"
|
64
|
+
not_end_all: "nekončí se všemi"
|
65
|
+
'true': "je pravdivé"
|
66
|
+
'false': "není pravdivé"
|
67
|
+
present: "je vyplněné"
|
68
|
+
blank: "je prázdné"
|
69
|
+
'null': "je null"
|
70
|
+
not_null: "není null"
|
@@ -0,0 +1,70 @@
|
|
1
|
+
es:
|
2
|
+
ransack:
|
3
|
+
search: "buscar"
|
4
|
+
predicate: "predicado"
|
5
|
+
and: "y"
|
6
|
+
or: "o"
|
7
|
+
any: "cualquier"
|
8
|
+
all: "todos"
|
9
|
+
combinator: "combinado"
|
10
|
+
attribute: "atributo"
|
11
|
+
value: "valor"
|
12
|
+
condition: "condición"
|
13
|
+
sort: "ordernar"
|
14
|
+
asc: "ascendente"
|
15
|
+
desc: "descendente"
|
16
|
+
predicates:
|
17
|
+
eq: "es igual a"
|
18
|
+
eq_any: "es igual a cualquier"
|
19
|
+
eq_all: "es igual a todos"
|
20
|
+
not_eq: "no es igual a"
|
21
|
+
not_eq_any: "no es igual a cualquier"
|
22
|
+
not_eq_all: "no es iguala todos"
|
23
|
+
matches: "coincidir"
|
24
|
+
matches_any: "coincidir a cualquier"
|
25
|
+
matches_all: "coincidir a todos"
|
26
|
+
does_not_match: "no coincide"
|
27
|
+
does_not_match_any: "no coincide con ninguna"
|
28
|
+
does_not_match_all: "no coincide con todos"
|
29
|
+
lt: "menor que"
|
30
|
+
lt_any: "menor que cualquier"
|
31
|
+
lt_all: "menor o igual a"
|
32
|
+
lteq: "menor que o igual a"
|
33
|
+
lteq_any: "menor o igual a cualquier"
|
34
|
+
lteq_all: "menor o igual a todos"
|
35
|
+
gt: "mayor que"
|
36
|
+
gt_any: "mayor que cualquier"
|
37
|
+
gt_all: "mayor que todos"
|
38
|
+
gteq: "mayor que o igual a"
|
39
|
+
gteq_any: "mayor que o igual a cualquier"
|
40
|
+
gteq_all: "mayor que o igual a todos"
|
41
|
+
in: "en"
|
42
|
+
in_any: "en cualquier"
|
43
|
+
in_all: "en todos"
|
44
|
+
not_in: "no en"
|
45
|
+
not_in_any: "no en cualquier"
|
46
|
+
not_in_all: "no en todos"
|
47
|
+
cont: "contiene"
|
48
|
+
cont_any: "contiene cualquier"
|
49
|
+
cont_all: "contiene todos"
|
50
|
+
not_cont: "no contiene"
|
51
|
+
not_cont_any: "no contiene ninguna"
|
52
|
+
not_cont_all: "no contiene toda"
|
53
|
+
start: "comienza con"
|
54
|
+
start_any: "comienza con cualquier"
|
55
|
+
start_all: "comienza con toda"
|
56
|
+
not_start: "no inicia con"
|
57
|
+
not_start_any: "no comienza con cualquier"
|
58
|
+
not_start_all: "no inicia con toda"
|
59
|
+
end: "termina con"
|
60
|
+
end_any: "termina con cualquier"
|
61
|
+
end_all: "termina con todo"
|
62
|
+
not_end: "no termina con"
|
63
|
+
not_end_any: "no termina con cualquier"
|
64
|
+
not_end_all: "no termina con todo"
|
65
|
+
'true': "es verdadero"
|
66
|
+
'false': "es falso"
|
67
|
+
present: "es presente"
|
68
|
+
blank: "está en blanco"
|
69
|
+
'null': "es nula"
|
70
|
+
not_null: "no es nula"
|
@@ -0,0 +1,70 @@
|
|
1
|
+
fr:
|
2
|
+
ransack:
|
3
|
+
search: "recherche"
|
4
|
+
predicate: "prédicat"
|
5
|
+
and: "et"
|
6
|
+
or: "ou"
|
7
|
+
any: "au moins un"
|
8
|
+
all: "tous"
|
9
|
+
combinator: "combinateur"
|
10
|
+
attribute: "attribut"
|
11
|
+
value: "valeur"
|
12
|
+
condition: "condition"
|
13
|
+
sort: "tri"
|
14
|
+
asc: "ascendant"
|
15
|
+
desc: "descendant"
|
16
|
+
predicates:
|
17
|
+
eq: "égal à"
|
18
|
+
eq_any: "égal à au moins un"
|
19
|
+
eq_all: "égal à tous"
|
20
|
+
not_eq: "différent de"
|
21
|
+
not_eq_any: "différent d'au moins un"
|
22
|
+
not_eq_all: "différent de tous"
|
23
|
+
matches: "correspond à"
|
24
|
+
matches_any: "correspond à au moins un"
|
25
|
+
matches_all: "correspond à tous"
|
26
|
+
does_not_match: "ne correspond pas à"
|
27
|
+
does_not_match_any: "ne correspond pas à au moins un"
|
28
|
+
does_not_match_all: "ne correspond à aucun"
|
29
|
+
lt: "inférieur à"
|
30
|
+
lt_any: "inférieur à au moins un"
|
31
|
+
lt_all: "inférieur à tous"
|
32
|
+
lteq: "inférieur ou égal à"
|
33
|
+
lteq_any: "inférieur ou égal à au moins un"
|
34
|
+
lteq_all: "inférieur ou égal à tous"
|
35
|
+
gt: "supérieur à"
|
36
|
+
gt_any: "supérieur à au moins un"
|
37
|
+
gt_all: "supérieur à tous"
|
38
|
+
gteq: "supérieur ou égal à"
|
39
|
+
gteq_any: "supérieur ou égal à au moins un"
|
40
|
+
gteq_all: "supérieur ou égal à tous"
|
41
|
+
in: "inclus dans"
|
42
|
+
in_any: "inclus dans au moins un"
|
43
|
+
in_all: "inclus dans tous"
|
44
|
+
not_in: "non inclus dans"
|
45
|
+
not_in_any: "non inclus dans au moins un"
|
46
|
+
not_in_all: "non inclus dans tous"
|
47
|
+
cont: "contient"
|
48
|
+
cont_any: "contient au moins un"
|
49
|
+
cont_all: "contient tous"
|
50
|
+
not_cont: "ne contient pas"
|
51
|
+
not_cont_any: "ne contient pas au moins un"
|
52
|
+
not_cont_all: "ne contient pas tous"
|
53
|
+
start: "commence par"
|
54
|
+
start_any: "commence par au moins un"
|
55
|
+
start_all: "commence par tous"
|
56
|
+
not_start: "ne commence pas par"
|
57
|
+
not_start_any: "ne commence pas par au moins un"
|
58
|
+
not_start_all: "ne commence pas par tous"
|
59
|
+
end: "finit par"
|
60
|
+
end_any: "finit par au moins un"
|
61
|
+
end_all: "finit par tous"
|
62
|
+
not_end: "ne finit pas par"
|
63
|
+
not_end_any: "ne finit pas par au moins un"
|
64
|
+
not_end_all: "ne finit pas par tous"
|
65
|
+
'true': "est vrai"
|
66
|
+
'false': "est faux"
|
67
|
+
present: "est présent"
|
68
|
+
blank: "est blanc"
|
69
|
+
'null': "est null"
|
70
|
+
not_null: "n'est pas null"
|
data/lib/ransack/locale/zh.yml
CHANGED
data/lib/ransack/search.rb
CHANGED
@@ -15,7 +15,7 @@ module Ransack
|
|
15
15
|
|
16
16
|
def initialize(object, params = {}, options = {})
|
17
17
|
params = {} unless params.is_a?(Hash)
|
18
|
-
params.delete_if { |k, v| v.blank? &&
|
18
|
+
(params ||= {}).delete_if { |k, v| [*v].all?{|i| i.blank? && i != false } }
|
19
19
|
@context = Context.for(object, options)
|
20
20
|
@context.auth_object = options[:auth_object]
|
21
21
|
@base = Nodes::Grouping.new(@context, 'and')
|
data/lib/ransack/version.rb
CHANGED
@@ -35,34 +35,29 @@ module Ransack
|
|
35
35
|
# end
|
36
36
|
#
|
37
37
|
# ransacker :doubled_name do |parent|
|
38
|
-
# Arel::Nodes::InfixOperation.new(
|
38
|
+
# Arel::Nodes::InfixOperation.new(
|
39
|
+
# '||', parent.table[:name], parent.table[:name]
|
40
|
+
# )
|
39
41
|
# end
|
40
42
|
|
41
43
|
it 'creates ransack attributes' do
|
42
44
|
s = Person.search(reversed_name_eq: 'htimS cirA')
|
43
45
|
s.result.should have(1).person
|
44
46
|
|
45
|
-
|
46
|
-
s.result.first.should eq Person.find_by(name: 'Aric Smith')
|
47
|
-
else
|
48
|
-
s.result.first.should eq Person.find_by_name('Aric Smith')
|
49
|
-
end
|
47
|
+
s.result.first.should eq Person.where(name: 'Aric Smith').first
|
50
48
|
end
|
51
49
|
|
52
50
|
it 'can be accessed through associations' do
|
53
51
|
s = Person.search(children_reversed_name_eq: 'htimS cirA')
|
54
52
|
s.result.to_sql.should match(
|
55
|
-
/#{quote_table_name("children_people")}.#{
|
53
|
+
/#{quote_table_name("children_people")}.#{
|
54
|
+
quote_column_name("name")} = 'Aric Smith'/
|
56
55
|
)
|
57
56
|
end
|
58
57
|
|
59
58
|
it 'allows an "attribute" to be an InfixOperation' do
|
60
59
|
s = Person.search(doubled_name_eq: 'Aric SmithAric Smith')
|
61
|
-
|
62
|
-
s.result.first.should eq Person.find_by(name: 'Aric Smith')
|
63
|
-
else
|
64
|
-
s.result.first.should eq Person.find_by_name('Aric Smith')
|
65
|
-
end
|
60
|
+
s.result.first.should eq Person.where(name: 'Aric Smith').first
|
66
61
|
end if defined?(Arel::Nodes::InfixOperation) && sane_adapter?
|
67
62
|
|
68
63
|
it "doesn't break #count if using InfixOperations" do
|
@@ -70,20 +65,18 @@ module Ransack
|
|
70
65
|
s.result.count.should eq 1
|
71
66
|
end if defined?(Arel::Nodes::InfixOperation) && sane_adapter?
|
72
67
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
end
|
68
|
+
it "should remove empty key value pairs from the params hash" do
|
69
|
+
s = Person.search(children_reversed_name_eq: '')
|
70
|
+
s.result.to_sql.should_not match /LEFT OUTER JOIN/
|
71
|
+
end
|
78
72
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
73
|
+
it "should keep proper key value pairs in the params hash" do
|
74
|
+
s = Person.search(children_reversed_name_eq: 'Testing')
|
75
|
+
s.result.to_sql.should match /LEFT OUTER JOIN/
|
76
|
+
end
|
83
77
|
|
84
|
-
|
85
|
-
|
86
|
-
end
|
78
|
+
it "should function correctly when nil is passed in" do
|
79
|
+
s = Person.search(nil)
|
87
80
|
end
|
88
81
|
|
89
82
|
it "should function correctly when using fields with dots in them" do
|
@@ -108,7 +101,8 @@ module Ransack
|
|
108
101
|
"s" => { "0" => { "dir" => "asc", "name" => "only_sort" } }
|
109
102
|
)
|
110
103
|
s.result.to_sql.should match(
|
111
|
-
/ORDER BY #{quote_table_name("people")}.#{
|
104
|
+
/ORDER BY #{quote_table_name("people")}.#{
|
105
|
+
quote_column_name("only_sort")} ASC/
|
112
106
|
)
|
113
107
|
end
|
114
108
|
|
@@ -117,21 +111,24 @@ module Ransack
|
|
117
111
|
"s" => { "0" => { "dir" => "asc", "name" => "only_search" } }
|
118
112
|
)
|
119
113
|
s.result.to_sql.should_not match(
|
120
|
-
/ORDER BY #{quote_table_name("people")}.#{
|
114
|
+
/ORDER BY #{quote_table_name("people")}.#{
|
115
|
+
quote_column_name("only_search")} ASC/
|
121
116
|
)
|
122
117
|
end
|
123
118
|
|
124
119
|
it 'allows search by "only_search" field' do
|
125
120
|
s = Person.search(only_search_eq: 'htimS cirA')
|
126
121
|
s.result.to_sql.should match(
|
127
|
-
/WHERE #{quote_table_name("people")}.#{
|
122
|
+
/WHERE #{quote_table_name("people")}.#{
|
123
|
+
quote_column_name("only_search")} = 'htimS cirA'/
|
128
124
|
)
|
129
125
|
end
|
130
126
|
|
131
127
|
it "can't be searched by 'only_sort'" do
|
132
128
|
s = Person.search(only_sort_eq: 'htimS cirA')
|
133
129
|
s.result.to_sql.should_not match(
|
134
|
-
/WHERE #{quote_table_name("people")}.#{
|
130
|
+
/WHERE #{quote_table_name("people")}.#{
|
131
|
+
quote_column_name("only_sort")} = 'htimS cirA'/
|
135
132
|
)
|
136
133
|
end
|
137
134
|
|
@@ -141,7 +138,8 @@ module Ransack
|
|
141
138
|
{ auth_object: :admin }
|
142
139
|
)
|
143
140
|
s.result.to_sql.should match(
|
144
|
-
/ORDER BY #{quote_table_name("people")}.#{
|
141
|
+
/ORDER BY #{quote_table_name("people")}.#{
|
142
|
+
quote_column_name("only_admin")} ASC/
|
145
143
|
)
|
146
144
|
end
|
147
145
|
|
@@ -150,7 +148,8 @@ module Ransack
|
|
150
148
|
"s" => { "0" => { "dir" => "asc", "name" => "only_admin" } }
|
151
149
|
)
|
152
150
|
s.result.to_sql.should_not match(
|
153
|
-
/ORDER BY #{quote_table_name("people")}.#{
|
151
|
+
/ORDER BY #{quote_table_name("people")}.#{
|
152
|
+
quote_column_name("only_admin")} ASC/
|
154
153
|
)
|
155
154
|
end
|
156
155
|
|
@@ -160,14 +159,16 @@ module Ransack
|
|
160
159
|
{ auth_object: :admin }
|
161
160
|
)
|
162
161
|
s.result.to_sql.should match(
|
163
|
-
/WHERE #{quote_table_name("people")}.#{
|
162
|
+
/WHERE #{quote_table_name("people")}.#{
|
163
|
+
quote_column_name("only_admin")} = 'htimS cirA'/
|
164
164
|
)
|
165
165
|
end
|
166
166
|
|
167
167
|
it "can't be searched by 'only_admin', if auth_object: nil" do
|
168
168
|
s = Person.search(only_admin_eq: 'htimS cirA')
|
169
169
|
s.result.to_sql.should_not match(
|
170
|
-
/WHERE #{quote_table_name("people")}.#{
|
170
|
+
/WHERE #{quote_table_name("people")}.#{
|
171
|
+
quote_column_name("only_admin")} = 'htimS cirA'/
|
171
172
|
)
|
172
173
|
end
|
173
174
|
end
|
@@ -26,54 +26,70 @@ module Ransack
|
|
26
26
|
end
|
27
27
|
|
28
28
|
describe '#sort_link with default search_key' do
|
29
|
-
subject { @controller.view_context
|
30
|
-
sort_link(
|
31
|
-
[:main_app, Person.search(sorts
|
29
|
+
subject { @controller.view_context
|
30
|
+
.sort_link(
|
31
|
+
[:main_app, Person.search(:sorts => ['name desc'])],
|
32
32
|
:name,
|
33
|
-
controller
|
33
|
+
:controller => 'people'
|
34
34
|
)
|
35
35
|
}
|
36
|
-
it {
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
36
|
+
it {
|
37
|
+
should match(
|
38
|
+
if ActiveRecord::VERSION::STRING =~ /^3\.[1-2]\./
|
39
|
+
/people\?q%5Bs%5D=name\+asc/
|
40
|
+
else
|
41
|
+
/people\?q(%5B|\[)s(%5D|\])=name\+asc/
|
42
|
+
end
|
43
|
+
)
|
44
|
+
}
|
45
|
+
it {
|
46
|
+
should match /sort_link desc/
|
47
|
+
}
|
48
|
+
it {
|
49
|
+
should match /Full Name ▼/
|
50
|
+
}
|
45
51
|
end
|
46
52
|
|
47
53
|
describe '#sort_link with default search_key defined as symbol' do
|
48
54
|
subject { @controller.
|
49
55
|
view_context.sort_link(
|
50
|
-
Person.search(
|
51
|
-
|
56
|
+
Person.search(
|
57
|
+
{ :sorts => ['name desc'] }, :search_key => :people_search
|
58
|
+
),
|
59
|
+
:name,
|
60
|
+
:controller => 'people'
|
61
|
+
)
|
62
|
+
}
|
63
|
+
it {
|
64
|
+
should match(
|
65
|
+
if ActiveRecord::VERSION::STRING =~ /^3\.[1-2]\./
|
66
|
+
/people\?people_search%5Bs%5D=name\+asc/
|
67
|
+
else
|
68
|
+
/people\?people_search(%5B|\[)s(%5D|\])=name\+asc/
|
69
|
+
end
|
52
70
|
)
|
53
71
|
}
|
54
|
-
it { should match(
|
55
|
-
if ActiveRecord::VERSION::STRING =~ /^3\.[1-2]\./
|
56
|
-
/people\?people_search%5Bs%5D=name\+asc/
|
57
|
-
else
|
58
|
-
/people\?people_search(%5B|\[)s(%5D|\])=name\+asc/
|
59
|
-
end)
|
60
|
-
}
|
61
72
|
end
|
62
73
|
|
63
74
|
describe '#sort_link with default search_key defined as string' do
|
64
75
|
subject {
|
65
76
|
@controller.view_context.sort_link(
|
66
|
-
Person.search(
|
67
|
-
|
77
|
+
Person.search(
|
78
|
+
{ :sorts => ['name desc'] }, :search_key => 'people_search'
|
79
|
+
),
|
80
|
+
:name,
|
81
|
+
:controller => 'people'
|
82
|
+
)
|
83
|
+
}
|
84
|
+
it {
|
85
|
+
should match(
|
86
|
+
if ActiveRecord::VERSION::STRING =~ /^3\.[1-2]\./
|
87
|
+
/people\?people_search%5Bs%5D=name\+asc/
|
88
|
+
else
|
89
|
+
/people\?people_search(%5B|\[)s(%5D|\])=name\+asc/
|
90
|
+
end
|
68
91
|
)
|
69
92
|
}
|
70
|
-
it { should match(
|
71
|
-
if ActiveRecord::VERSION::STRING =~ /^3\.[1-2]\./
|
72
|
-
/people\?people_search%5Bs%5D=name\+asc/
|
73
|
-
else
|
74
|
-
/people\?people_search(%5B|\[)s(%5D|\])=name\+asc/
|
75
|
-
end)
|
76
|
-
}
|
77
93
|
end
|
78
94
|
|
79
95
|
context 'view has existing parameters' do
|
@@ -83,8 +99,11 @@ module Ransack
|
|
83
99
|
describe '#sort_link should not remove existing params' do
|
84
100
|
subject {
|
85
101
|
@controller.view_context.sort_link(
|
86
|
-
Person.search(
|
87
|
-
|
102
|
+
Person.search(
|
103
|
+
{ :sorts => ['name desc'] }, :search_key => 'people_search'
|
104
|
+
),
|
105
|
+
:name,
|
106
|
+
:controller => 'people'
|
88
107
|
)
|
89
108
|
}
|
90
109
|
it {
|
@@ -92,6 +111,37 @@ module Ransack
|
|
92
111
|
}
|
93
112
|
end
|
94
113
|
end
|
114
|
+
|
115
|
+
describe '#search_form_for with default format' do
|
116
|
+
subject {
|
117
|
+
@controller.view_context
|
118
|
+
.search_form_for(Person.search) {}
|
119
|
+
}
|
120
|
+
it {
|
121
|
+
should match /action="\/people"/
|
122
|
+
}
|
123
|
+
end
|
124
|
+
|
125
|
+
describe '#search_form_for with pdf format' do
|
126
|
+
subject {
|
127
|
+
@controller.view_context
|
128
|
+
.search_form_for(Person.search, :format => :pdf) {}
|
129
|
+
}
|
130
|
+
it {
|
131
|
+
should match /action="\/people.pdf"/
|
132
|
+
}
|
133
|
+
end
|
134
|
+
|
135
|
+
describe '#search_form_for with json format' do
|
136
|
+
subject {
|
137
|
+
@controller.view_context
|
138
|
+
.search_form_for(Person.search, :format => :json) {}
|
139
|
+
}
|
140
|
+
it {
|
141
|
+
should match /action="\/people.json"/
|
142
|
+
}
|
143
|
+
end
|
144
|
+
|
95
145
|
end
|
96
146
|
end
|
97
147
|
end
|
data/spec/ransack/search_spec.rb
CHANGED
@@ -2,6 +2,39 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module Ransack
|
4
4
|
describe Search do
|
5
|
+
describe '#initialize' do
|
6
|
+
it "removes empty conditions before building" do
|
7
|
+
Search.any_instance.should_receive(:build).with({})
|
8
|
+
Search.new(Person, :name_eq => '')
|
9
|
+
end
|
10
|
+
|
11
|
+
it "keeps conditions with a false value before building" do
|
12
|
+
Search.any_instance.should_receive(:build).with({"name_eq" => false})
|
13
|
+
Search.new(Person, :name_eq => false)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "keeps conditions with a value before building" do
|
17
|
+
Search.any_instance.should_receive(:build).with({"name_eq" => 'foobar'})
|
18
|
+
Search.new(Person, :name_eq => 'foobar')
|
19
|
+
end
|
20
|
+
|
21
|
+
it "removes empty suffixed conditions before building" do
|
22
|
+
Search.any_instance.should_receive(:build).with({})
|
23
|
+
Search.new(Person, :name_eq_any => [''])
|
24
|
+
end
|
25
|
+
|
26
|
+
it "keeps suffixed conditions with a false value before building" do
|
27
|
+
Search.any_instance.should_receive(:build).with({"name_eq_any" => [false]})
|
28
|
+
Search.new(Person, :name_eq_any => [false])
|
29
|
+
end
|
30
|
+
|
31
|
+
it "keeps suffixed conditions with a value before building" do
|
32
|
+
Search.any_instance.should_receive(:build).with({"name_eq_any" => ['foobar']})
|
33
|
+
Search.new(Person, :name_eq_any => ['foobar'])
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
end
|
5
38
|
|
6
39
|
describe '#initialize' do
|
7
40
|
it 'does not raise exception for string :params argument' do
|
@@ -180,42 +213,26 @@ module Ransack
|
|
180
213
|
second.should match /#{children_people_name_field} = 'Bert'/
|
181
214
|
end
|
182
215
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
end
|
197
|
-
else
|
198
|
-
it 'returns distinct records when passed :distinct => true' do
|
199
|
-
search = Search.new(
|
200
|
-
Person, :g => [
|
201
|
-
{ :m => 'or',
|
202
|
-
:comments_body_cont => 'e',
|
203
|
-
:articles_comments_body_cont => 'e'
|
204
|
-
}
|
205
|
-
]
|
206
|
-
)
|
207
|
-
if ActiveRecord::VERSION::MAJOR == 3
|
208
|
-
all_or_load, uniq_or_distinct = :all, :uniq
|
209
|
-
else
|
210
|
-
all_or_load, uniq_or_distinct = :load, :distinct
|
211
|
-
end
|
212
|
-
search.result.send(all_or_load).
|
213
|
-
should have(9000).items
|
214
|
-
search.result(:distinct => true).
|
215
|
-
should have(10).items
|
216
|
-
search.result.send(all_or_load).send(uniq_or_distinct).
|
217
|
-
should eq search.result(:distinct => true).send(all_or_load)
|
216
|
+
it 'returns distinct records when passed :distinct => true' do
|
217
|
+
search = Search.new(
|
218
|
+
Person, :g => [
|
219
|
+
{ :m => 'or',
|
220
|
+
:comments_body_cont => 'e',
|
221
|
+
:articles_comments_body_cont => 'e'
|
222
|
+
}
|
223
|
+
]
|
224
|
+
)
|
225
|
+
if ActiveRecord::VERSION::MAJOR == 3
|
226
|
+
all_or_load, uniq_or_distinct = :all, :uniq
|
227
|
+
else
|
228
|
+
all_or_load, uniq_or_distinct = :load, :distinct
|
218
229
|
end
|
230
|
+
search.result.send(all_or_load).
|
231
|
+
should have(9000).items
|
232
|
+
search.result(:distinct => true).
|
233
|
+
should have(10).items
|
234
|
+
search.result.send(all_or_load).send(uniq_or_distinct).
|
235
|
+
should eq search.result(:distinct => true).send(all_or_load)
|
219
236
|
end
|
220
237
|
end
|
221
238
|
|
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.2.
|
4
|
+
version: 1.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ernie Miller
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-04-
|
12
|
+
date: 2014-04-30 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: actionpack
|
@@ -210,7 +210,10 @@ files:
|
|
210
210
|
- lib/ransack/helpers.rb
|
211
211
|
- lib/ransack/helpers/form_builder.rb
|
212
212
|
- lib/ransack/helpers/form_helper.rb
|
213
|
+
- lib/ransack/locale/cs.yml
|
213
214
|
- lib/ransack/locale/en.yml
|
215
|
+
- lib/ransack/locale/es.yml
|
216
|
+
- lib/ransack/locale/fr.yml
|
214
217
|
- lib/ransack/locale/zh.yml
|
215
218
|
- lib/ransack/naming.rb
|
216
219
|
- lib/ransack/nodes.rb
|
@@ -269,7 +272,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
269
272
|
version: '0'
|
270
273
|
requirements: []
|
271
274
|
rubyforge_project: ransack
|
272
|
-
rubygems_version: 2.2.
|
275
|
+
rubygems_version: 2.2.0
|
273
276
|
signing_key:
|
274
277
|
specification_version: 4
|
275
278
|
summary: Object-based searching for ActiveRecord (currently).
|