ransack 1.2.2 → 1.2.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 +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
|
-
[![Build Status](https://travis-ci.org/activerecord-hackery/ransack.svg)]
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
3
|
+
[![Build Status](https://travis-ci.org/activerecord-hackery/ransack.svg)]
|
4
|
+
(https://travis-ci.org/activerecord-hackery/ransack)
|
5
|
+
[![Gem Version](https://badge.fury.io/rb/ransack.svg)]
|
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).
|