ransack 0.7.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.travis.yml +10 -3
- data/CONTRIBUTING.md +1 -2
- data/Gemfile +3 -3
- data/README.md +78 -57
- data/lib/ransack/adapters/active_record.rb +2 -0
- data/lib/ransack/adapters/active_record/3.0/context.rb +9 -15
- data/lib/ransack/adapters/active_record/3.1/context.rb +9 -14
- data/lib/ransack/adapters/active_record/3.2/context.rb +44 -0
- data/lib/ransack/adapters/active_record/context.rb +11 -9
- data/lib/ransack/constants.rb +6 -1
- data/lib/ransack/context.rb +15 -1
- data/lib/ransack/helpers/form_builder.rb +2 -1
- data/lib/ransack/helpers/form_helper.rb +3 -2
- data/lib/ransack/locale/es.yml +1 -1
- data/lib/ransack/locale/fr.yml +70 -0
- data/lib/ransack/translate.rb +9 -8
- data/lib/ransack/version.rb +1 -1
- data/ransack.gemspec +3 -3
- data/spec/ransack/adapters/active_record/context_spec.rb +6 -0
- data/spec/ransack/helpers/form_builder_spec.rb +16 -6
- data/spec/ransack/helpers/form_helper_spec.rb +57 -10
- data/spec/ransack/predicate_spec.rb +37 -4
- data/spec/ransack/search_spec.rb +50 -35
- data/spec/spec_helper.rb +2 -0
- data/spec/support/en.yml +3 -1
- data/spec/support/schema.rb +40 -35
- metadata +16 -29
data/lib/ransack/constants.rb
CHANGED
@@ -23,7 +23,12 @@ module Ransack
|
|
23
23
|
module_function
|
24
24
|
# replace % \ to \% \\
|
25
25
|
def escape_wildcards(unescaped)
|
26
|
-
|
26
|
+
if ActiveRecord::VERSION::MAJOR == 3
|
27
|
+
unescaped.to_s.gsub(/([\\|\%|.])/, '\\\\\\1')
|
28
|
+
else
|
29
|
+
unescaped.to_s.gsub(/\\/){ "\\\\" }.gsub(/%/, "\\%")
|
30
|
+
end
|
27
31
|
end
|
32
|
+
|
28
33
|
end
|
29
34
|
end
|
data/lib/ransack/context.rb
CHANGED
@@ -28,7 +28,7 @@ module Ransack
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def initialize(object, options = {})
|
31
|
-
@object = object
|
31
|
+
@object = relation_for(object)
|
32
32
|
@klass = @object.klass
|
33
33
|
@join_dependency = join_dependency(@object)
|
34
34
|
@join_type = options[:join_type] || Arel::OuterJoin
|
@@ -44,6 +44,20 @@ module Ransack
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
+
def klassify(obj)
|
48
|
+
if Class === obj && ::ActiveRecord::Base > obj
|
49
|
+
obj
|
50
|
+
elsif obj.respond_to? :klass
|
51
|
+
obj.klass
|
52
|
+
elsif obj.respond_to? :active_record # Rails 3
|
53
|
+
obj.active_record
|
54
|
+
elsif obj.respond_to? :base_klass # Rails 4
|
55
|
+
obj.base_klass
|
56
|
+
else
|
57
|
+
raise ArgumentError, "Don't know how to klassify #{obj}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
47
61
|
# Convert a string representing a chain of associations and an attribute
|
48
62
|
# into the attribute itself
|
49
63
|
def contextualize(str)
|
@@ -59,11 +59,12 @@ module Ransack
|
|
59
59
|
query_hash = {}
|
60
60
|
query_hash[search.context.search_key] = search_params.merge(:s => "#{attr_name} #{new_dir}")
|
61
61
|
options.merge!(query_hash)
|
62
|
+
options_for_url = params.merge options
|
62
63
|
|
63
64
|
url = if routing_proxy && respond_to?(routing_proxy)
|
64
|
-
send(routing_proxy).url_for(
|
65
|
+
send(routing_proxy).url_for(options_for_url)
|
65
66
|
else
|
66
|
-
url_for(
|
67
|
+
url_for(options_for_url)
|
67
68
|
end
|
68
69
|
|
69
70
|
link_to [ERB::Util.h(name), order_indicator_for(current_dir)].compact.join(' ').html_safe,
|
data/lib/ransack/locale/es.yml
CHANGED
@@ -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/translate.rb
CHANGED
@@ -23,7 +23,7 @@ module Ransack
|
|
23
23
|
attribute_names = attributes_str.split(/_and_|_or_/)
|
24
24
|
combinator = attributes_str.match(/_and_/) ? :and : :or
|
25
25
|
defaults = base_ancestors.map do |klass|
|
26
|
-
:"ransack.attributes.#{klass.model_name.
|
26
|
+
:"ransack.attributes.#{klass.model_name.singular}.#{original_name}"
|
27
27
|
end
|
28
28
|
|
29
29
|
translated_names = attribute_names.map do |attr|
|
@@ -50,7 +50,7 @@ module Ransack
|
|
50
50
|
raise ArgumentError, "A context is required to translate associations"
|
51
51
|
end
|
52
52
|
|
53
|
-
defaults = key.blank? ? [:"#{context.klass.i18n_scope}.models.#{context.klass.model_name.
|
53
|
+
defaults = key.blank? ? [:"#{context.klass.i18n_scope}.models.#{context.klass.model_name.singular}"] : [:"ransack.associations.#{context.klass.model_name.singular}.#{key}"]
|
54
54
|
defaults << context.traverse(key).model_name.human
|
55
55
|
options = {:count => 1, :default => defaults}
|
56
56
|
I18n.translate(defaults.shift, options)
|
@@ -65,19 +65,20 @@ module Ransack
|
|
65
65
|
interpolations = {}
|
66
66
|
interpolations[:attr_fallback_name] = I18n.translate(
|
67
67
|
(associated_class ?
|
68
|
-
:"ransack.attributes.#{associated_class.model_name.
|
69
|
-
:"ransack.attributes.#{context.klass.model_name.
|
68
|
+
:"ransack.attributes.#{associated_class.model_name.singular}.#{attr_name}" :
|
69
|
+
:"ransack.attributes.#{context.klass.model_name.singular}.#{attr_name}"
|
70
70
|
),
|
71
71
|
:default => [
|
72
72
|
(associated_class ?
|
73
|
-
:"#{associated_class.i18n_scope}.attributes.#{associated_class.model_name.
|
74
|
-
:"#{context.klass.i18n_scope}.attributes.#{context.klass.model_name.
|
73
|
+
:"#{associated_class.i18n_scope}.attributes.#{associated_class.model_name.singular}.#{attr_name}" :
|
74
|
+
:"#{context.klass.i18n_scope}.attributes.#{context.klass.model_name.singular}.#{attr_name}"
|
75
75
|
),
|
76
|
+
:".attributes.#{attr_name}",
|
76
77
|
attr_name.humanize
|
77
78
|
]
|
78
79
|
)
|
79
80
|
defaults = [
|
80
|
-
:"ransack.attributes.#{context.klass.model_name.
|
81
|
+
:"ransack.attributes.#{context.klass.model_name.singular}.#{name}"
|
81
82
|
]
|
82
83
|
if include_associations && associated_class
|
83
84
|
defaults << '%{association_name} %{attr_fallback_name}'
|
@@ -89,4 +90,4 @@ module Ransack
|
|
89
90
|
I18n.translate(defaults.shift, options.merge(interpolations))
|
90
91
|
end
|
91
92
|
end
|
92
|
-
end
|
93
|
+
end
|
data/lib/ransack/version.rb
CHANGED
data/ransack.gemspec
CHANGED
@@ -14,9 +14,9 @@ Gem::Specification.new do |s|
|
|
14
14
|
|
15
15
|
s.rubyforge_project = "ransack"
|
16
16
|
|
17
|
-
s.add_dependency 'activerecord', '
|
18
|
-
s.add_dependency 'actionpack', '
|
19
|
-
s.add_dependency 'polyamorous', '~> 0.
|
17
|
+
s.add_dependency 'activerecord', '>= 3.0'
|
18
|
+
s.add_dependency 'actionpack', '>= 3.0'
|
19
|
+
s.add_dependency 'polyamorous', '~> 0.6.0'
|
20
20
|
s.add_development_dependency 'rspec', '~> 2.8.0'
|
21
21
|
s.add_development_dependency 'machinist', '~> 1.0.6'
|
22
22
|
s.add_development_dependency 'faker', '~> 0.9.5'
|
@@ -6,6 +6,12 @@ module Ransack
|
|
6
6
|
describe Context do
|
7
7
|
subject { Context.new(Person) }
|
8
8
|
|
9
|
+
describe '#relation_for' do
|
10
|
+
it 'returns relation for given object' do
|
11
|
+
subject.object.should be_an ::ActiveRecord::Relation
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
9
15
|
describe '#evaluate' do
|
10
16
|
it 'evaluates search obects' do
|
11
17
|
search = Search.new(Person, :name_eq => 'Joe Blow')
|
@@ -7,7 +7,7 @@ module Ransack
|
|
7
7
|
router = ActionDispatch::Routing::RouteSet.new
|
8
8
|
router.draw do
|
9
9
|
resources :people
|
10
|
-
|
10
|
+
get ':controller(/:action(/:id(.:format)))'
|
11
11
|
end
|
12
12
|
|
13
13
|
include router.url_helpers
|
@@ -48,11 +48,21 @@ module Ransack
|
|
48
48
|
end
|
49
49
|
|
50
50
|
describe '#sort_link' do
|
51
|
-
|
51
|
+
it 'sort_link for ransack attribute' do
|
52
|
+
sort_link = @f.sort_link :name, :controller => 'people'
|
53
|
+
if ActiveRecord::VERSION::STRING =~ /^3\.[1-2]\./
|
54
|
+
sort_link.should match /people\?q%5Bs%5D=name\+asc/
|
55
|
+
else
|
56
|
+
sort_link.should match /people\?q(%5B|\[)s(%5D|\])=name\+asc/
|
57
|
+
end
|
58
|
+
sort_link.should match /sort_link/
|
59
|
+
sort_link.should match /Full Name<\/a>/
|
60
|
+
end
|
52
61
|
|
53
|
-
it
|
54
|
-
|
55
|
-
|
62
|
+
it 'sort_link for common attribute' do
|
63
|
+
sort_link = @f.sort_link :id, :controller => 'people'
|
64
|
+
sort_link.should match /id<\/a>/
|
65
|
+
end
|
56
66
|
end
|
57
67
|
|
58
68
|
describe '#submit' do
|
@@ -124,4 +134,4 @@ module Ransack
|
|
124
134
|
end
|
125
135
|
end
|
126
136
|
end
|
127
|
-
end
|
137
|
+
end
|
@@ -7,7 +7,7 @@ module Ransack
|
|
7
7
|
router = ActionDispatch::Routing::RouteSet.new
|
8
8
|
router.draw do
|
9
9
|
resources :people
|
10
|
-
|
10
|
+
get ':controller(/:action(/:id(.:format)))'
|
11
11
|
end
|
12
12
|
|
13
13
|
include router.url_helpers
|
@@ -26,24 +26,71 @@ module Ransack
|
|
26
26
|
end
|
27
27
|
|
28
28
|
describe '#sort_link with default search_key' do
|
29
|
-
subject {
|
30
|
-
|
29
|
+
subject {
|
30
|
+
@controller.view_context.sort_link(
|
31
|
+
[:main_app, Person.search(:sorts => ['name desc'])],
|
32
|
+
:name, :controller => 'people'
|
33
|
+
)
|
34
|
+
}
|
35
|
+
it { should match(
|
36
|
+
if ActiveRecord::VERSION::STRING =~ /^3\.[1-2]\./
|
37
|
+
/people\?q%5Bs%5D=name\+asc/
|
38
|
+
else
|
39
|
+
/people\?q(%5B|\[)s(%5D|\])=name\+asc/
|
40
|
+
end)
|
41
|
+
}
|
31
42
|
it { should match /sort_link desc/ }
|
32
43
|
it { should match /Full Name ▼/ }
|
33
44
|
end
|
34
45
|
|
35
46
|
describe '#sort_link with default search_key defined as symbol' do
|
36
|
-
subject { @controller.
|
37
|
-
|
38
|
-
|
39
|
-
|
47
|
+
subject { @controller.
|
48
|
+
view_context.sort_link(
|
49
|
+
Person.search({ :sorts => ['name desc'] }, :search_key => :people_search),
|
50
|
+
:name, :controller => 'people'
|
51
|
+
)
|
52
|
+
}
|
53
|
+
it { should match(
|
54
|
+
if ActiveRecord::VERSION::STRING =~ /^3\.[1-2]\./
|
55
|
+
/people\?people_search%5Bs%5D=name\+asc/
|
56
|
+
else
|
57
|
+
/people\?people_search(%5B|\[)s(%5D|\])=name\+asc/
|
58
|
+
end)
|
59
|
+
}
|
40
60
|
end
|
41
61
|
|
42
62
|
describe '#sort_link with default search_key defined as string' do
|
43
|
-
subject {
|
44
|
-
|
63
|
+
subject {
|
64
|
+
@controller.view_context.sort_link(
|
65
|
+
Person.search({ :sorts => ['name desc'] }, :search_key => 'people_search'),
|
66
|
+
:name, :controller => 'people'
|
67
|
+
)
|
68
|
+
}
|
69
|
+
it { should match(
|
70
|
+
if ActiveRecord::VERSION::STRING =~ /^3\.[1-2]\./
|
71
|
+
/people\?people_search%5Bs%5D=name\+asc/
|
72
|
+
else
|
73
|
+
/people\?people_search(%5B|\[)s(%5D|\])=name\+asc/
|
74
|
+
end)
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
45
78
|
|
46
|
-
|
79
|
+
context 'view has existing parameters' do
|
80
|
+
before do
|
81
|
+
@controller.view_context.params.merge!({ :exist => 'existing' })
|
82
|
+
end
|
83
|
+
describe '#sort_link should not remove existing params' do
|
84
|
+
subject {
|
85
|
+
@controller.view_context.sort_link(
|
86
|
+
Person.search({ :sorts => ['name desc'] }, :search_key => 'people_search'),
|
87
|
+
:name, :controller => 'people'
|
88
|
+
)
|
89
|
+
}
|
90
|
+
it {
|
91
|
+
should match /exist\=existing/
|
92
|
+
}
|
93
|
+
end
|
47
94
|
end
|
48
95
|
end
|
49
96
|
end
|
@@ -7,6 +7,24 @@ module Ransack
|
|
7
7
|
@s = Search.new(Person)
|
8
8
|
end
|
9
9
|
|
10
|
+
shared_examples 'wildcard escaping' do |method, regexp|
|
11
|
+
it 'automatically converts integers to strings' do
|
12
|
+
subject.parent_id_cont = 1
|
13
|
+
expect { subject.result }.to_not raise_error
|
14
|
+
end
|
15
|
+
|
16
|
+
it (
|
17
|
+
if ActiveRecord::VERSION::MAJOR == 3
|
18
|
+
"escapes '%', '.' and '\\\\' in value"
|
19
|
+
else
|
20
|
+
"escapes % and \\ in value"
|
21
|
+
end
|
22
|
+
) do
|
23
|
+
subject.send(:"#{method}=", '%._\\')
|
24
|
+
subject.result.to_sql.should match(regexp)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
10
28
|
describe 'eq' do
|
11
29
|
it 'generates an equality condition for boolean true' do
|
12
30
|
@s.awesome_eq = true
|
@@ -25,17 +43,32 @@ module Ransack
|
|
25
43
|
end
|
26
44
|
|
27
45
|
describe 'cont' do
|
46
|
+
|
47
|
+
it_has_behavior 'wildcard escaping', :name_cont, (
|
48
|
+
if ActiveRecord::VERSION::MAJOR == 3
|
49
|
+
/"people"."name" LIKE '%\\%\\._\\\\%'/
|
50
|
+
else
|
51
|
+
/"people"."name" LIKE '%\\%._\\\\%'/
|
52
|
+
end) do
|
53
|
+
subject { @s }
|
54
|
+
end
|
55
|
+
|
28
56
|
it 'generates a LIKE query with value surrounded by %' do
|
29
57
|
@s.name_cont = 'ric'
|
30
58
|
@s.result.to_sql.should match /"people"."name" LIKE '%ric%'/
|
31
59
|
end
|
32
|
-
it 'escapes %, _ and \\ in value' do
|
33
|
-
@s.name_cont = '%_\\'
|
34
|
-
@s.result.to_sql.should match /"people"."name" LIKE '%\\%\\_\\\\%'/
|
35
|
-
end
|
36
60
|
end
|
37
61
|
|
38
62
|
describe 'not_cont' do
|
63
|
+
it_has_behavior 'wildcard escaping', :name_not_cont, (
|
64
|
+
if ActiveRecord::VERSION::MAJOR == 3
|
65
|
+
/"people"."name" NOT LIKE '%\\%\\._\\\\%'/
|
66
|
+
else
|
67
|
+
/"people"."name" NOT LIKE '%\\%._\\\\%'/
|
68
|
+
end) do
|
69
|
+
subject { @s }
|
70
|
+
end
|
71
|
+
|
39
72
|
it 'generates a NOT LIKE query with value surrounded by %' do
|
40
73
|
@s.name_not_cont = 'ric'
|
41
74
|
@s.result.to_sql.should match /"people"."name" NOT LIKE '%ric%'/
|
data/spec/ransack/search_spec.rb
CHANGED
@@ -32,8 +32,10 @@ module Ransack
|
|
32
32
|
end
|
33
33
|
|
34
34
|
it 'creates Conditions for multiple polymorphic belongs_to association attributes' do
|
35
|
-
search = Search.new(Note,
|
36
|
-
|
35
|
+
search = Search.new(Note,
|
36
|
+
:notable_of_Person_type_name_or_notable_of_Article_type_title_eq => 'Ernie')
|
37
|
+
condition = search.
|
38
|
+
base[:notable_of_Person_type_name_or_notable_of_Article_type_title_eq]
|
37
39
|
condition.should be_a Nodes::Condition
|
38
40
|
condition.predicate.name.should eq 'eq'
|
39
41
|
condition.attributes.first.name.should eq 'notable_of_Person_type_name'
|
@@ -50,8 +52,8 @@ module Ransack
|
|
50
52
|
it 'accepts arrays of groupings' do
|
51
53
|
search = Search.new(Person,
|
52
54
|
:g => [
|
53
|
-
{:m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie'},
|
54
|
-
{:m => 'or', :name_eq => 'Bert', :children_name_eq => 'Bert'},
|
55
|
+
{ :m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie' },
|
56
|
+
{ :m => 'or', :name_eq => 'Bert', :children_name_eq => 'Bert' },
|
55
57
|
]
|
56
58
|
)
|
57
59
|
ors = search.groupings
|
@@ -66,8 +68,8 @@ module Ransack
|
|
66
68
|
it 'accepts "attributes" hashes for groupings' do
|
67
69
|
search = Search.new(Person,
|
68
70
|
:g => {
|
69
|
-
'0' => {:m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie'},
|
70
|
-
'1' => {:m => 'or', :name_eq => 'Bert', :children_name_eq => 'Bert'},
|
71
|
+
'0' => { :m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie' },
|
72
|
+
'1' => { :m => 'or', :name_eq => 'Bert', :children_name_eq => 'Bert' },
|
71
73
|
}
|
72
74
|
)
|
73
75
|
ors = search.groupings
|
@@ -82,8 +84,8 @@ module Ransack
|
|
82
84
|
it 'accepts "attributes" hashes for conditions' do
|
83
85
|
search = Search.new(Person,
|
84
86
|
:c => {
|
85
|
-
'0' => {:a => ['name'], :p => 'eq', :v => ['Ernie']},
|
86
|
-
'1' => {:a => ['children_name', 'parent_name'], :p => 'eq', :v => ['Ernie'], :m => 'or'}
|
87
|
+
'0' => { :a => ['name'], :p => 'eq', :v => ['Ernie'] },
|
88
|
+
'1' => { :a => ['children_name', 'parent_name'], :p => 'eq', :v => ['Ernie'], :m => 'or' }
|
87
89
|
}
|
88
90
|
)
|
89
91
|
conditions = search.base.conditions
|
@@ -93,8 +95,7 @@ module Ransack
|
|
93
95
|
|
94
96
|
it 'creates Conditions for custom predicates that take arrays' do
|
95
97
|
Ransack.configure do |config|
|
96
|
-
config.add_predicate 'ary_pred',
|
97
|
-
:wants_array => true
|
98
|
+
config.add_predicate 'ary_pred', :wants_array => true
|
98
99
|
end
|
99
100
|
|
100
101
|
search = Search.new(Person, :name_ary_pred => ['Ernie', 'Bert'])
|
@@ -135,11 +136,12 @@ module Ransack
|
|
135
136
|
|
136
137
|
it 'evaluates nested conditions' do
|
137
138
|
search = Search.new(Person, :children_name_eq => 'Ernie',
|
138
|
-
:g => [
|
139
|
-
:m => 'or',
|
140
|
-
|
141
|
-
|
142
|
-
|
139
|
+
:g => [
|
140
|
+
{ :m => 'or',
|
141
|
+
:name_eq => 'Ernie',
|
142
|
+
:children_children_name_eq => 'Ernie'
|
143
|
+
}
|
144
|
+
]
|
143
145
|
)
|
144
146
|
search.result.should be_an ActiveRecord::Relation
|
145
147
|
where = search.result.where_values.first
|
@@ -151,8 +153,8 @@ module Ransack
|
|
151
153
|
it 'evaluates arrays of groupings' do
|
152
154
|
search = Search.new(Person,
|
153
155
|
:g => [
|
154
|
-
{:m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie'},
|
155
|
-
{:m => 'or', :name_eq => 'Bert', :children_name_eq => 'Bert'},
|
156
|
+
{ :m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie' },
|
157
|
+
{ :m => 'or', :name_eq => 'Bert', :children_name_eq => 'Bert' },
|
156
158
|
]
|
157
159
|
)
|
158
160
|
search.result.should be_an ActiveRecord::Relation
|
@@ -166,10 +168,25 @@ module Ransack
|
|
166
168
|
end
|
167
169
|
|
168
170
|
it 'returns distinct records when passed :distinct => true' do
|
169
|
-
search = Search.new(
|
170
|
-
|
171
|
-
|
172
|
-
|
171
|
+
search = Search.new(
|
172
|
+
Person, :g => [
|
173
|
+
{ :m => 'or',
|
174
|
+
:comments_body_cont => 'e',
|
175
|
+
:articles_comments_body_cont => 'e'
|
176
|
+
}
|
177
|
+
]
|
178
|
+
)
|
179
|
+
if ActiveRecord::VERSION::MAJOR == 3
|
180
|
+
all_or_load, uniq_or_distinct = :all, :uniq
|
181
|
+
else
|
182
|
+
all_or_load, uniq_or_distinct = :load, :distinct
|
183
|
+
end
|
184
|
+
search.result.send(all_or_load).
|
185
|
+
should have(920).items
|
186
|
+
search.result(:distinct => true).
|
187
|
+
should have(330).items
|
188
|
+
search.result.send(all_or_load).send(uniq_or_distinct).
|
189
|
+
should eq search.result(:distinct => true).send(all_or_load)
|
173
190
|
end
|
174
191
|
end
|
175
192
|
|
@@ -201,22 +218,21 @@ module Ransack
|
|
201
218
|
|
202
219
|
it 'creates sorts based on multiple attributes/directions in hash format' do
|
203
220
|
@s.sorts = {
|
204
|
-
'0' => {
|
205
|
-
|
206
|
-
:dir => 'desc'
|
207
|
-
},
|
208
|
-
'1' => {
|
209
|
-
:name => 'name',
|
210
|
-
:dir => 'asc'
|
211
|
-
}
|
221
|
+
'0' => { :name => 'id', :dir => 'desc' },
|
222
|
+
'1' => { :name => 'name', :dir => 'asc' }
|
212
223
|
}
|
213
224
|
@s.sorts.should have(2).items
|
214
|
-
@s.sorts.should be_all {|s| Nodes::Sort === s}
|
215
|
-
id_sort = @s.sorts.detect {|s| s.name == 'id'}
|
216
|
-
name_sort = @s.sorts.detect {|s| s.name == 'name'}
|
225
|
+
@s.sorts.should be_all { |s| Nodes::Sort === s }
|
226
|
+
id_sort = @s.sorts.detect { |s| s.name == 'id' }
|
227
|
+
name_sort = @s.sorts.detect { |s| s.name == 'name' }
|
217
228
|
id_sort.dir.should eq 'desc'
|
218
229
|
name_sort.dir.should eq 'asc'
|
219
230
|
end
|
231
|
+
|
232
|
+
it 'overrides existing sort' do
|
233
|
+
@s.sorts = 'id asc'
|
234
|
+
@s.result.first.id.should eq 1
|
235
|
+
end
|
220
236
|
end
|
221
237
|
|
222
238
|
describe '#method_missing' do
|
@@ -225,7 +241,7 @@ module Ransack
|
|
225
241
|
end
|
226
242
|
|
227
243
|
it 'raises NoMethodError when sent an invalid attribute' do
|
228
|
-
expect {@s.blah}.to raise_error NoMethodError
|
244
|
+
expect { @s.blah }.to raise_error NoMethodError
|
229
245
|
end
|
230
246
|
|
231
247
|
it 'sets condition attributes when sent valid attributes' do
|
@@ -234,8 +250,7 @@ module Ransack
|
|
234
250
|
end
|
235
251
|
|
236
252
|
it 'allows chaining to access nested conditions' do
|
237
|
-
@s.groupings = [{:m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie'}]
|
238
|
-
@s.groupings.first.name_eq.should eq 'Ernie'
|
253
|
+
@s.groupings = [{ :m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie' }]
|
239
254
|
@s.groupings.first.children_name_eq.should eq 'Ernie'
|
240
255
|
end
|
241
256
|
end
|