ransack_abbreviator 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,28 @@
1
+ require "ostruct"
2
+ require "yaml"
3
+ require 'ransack_abbreviator/configuration'
4
+ require 'ransack_abbreviator/constants'
5
+
6
+ module RansackAbbreviator
7
+ extend Configuration
8
+
9
+ class DuplicateColumnAbbreviation < StandardError; end;
10
+ end
11
+
12
+ RansackAbbreviator.configure do |config|
13
+ parsed_config = OpenStruct.new((YAML.load_file(config.config_dir.join("ransack_abbreviator.yml")) rescue {}))
14
+ ransack_abbreviations = parsed_config.ransack_abbreviations
15
+ if !(ransack_abbreviations["columns"].values & RansackAbbreviator::Constants::RESERVED_KEYWORDS).blank? ||
16
+ !(ransack_abbreviations["associations"].values & RansackAbbreviator::Constants::RESERVED_KEYWORDS).blank?
17
+ fail "You used a reserved keyword as an abbreviation. Reserverd keywords: #{RansackAbbreviator::Constants::RESERVED_KEYWORDS.join(", ")}"
18
+ end
19
+ config.column_abbreviations = ransack_abbreviations["columns"] if ransack_abbreviations["columns"]
20
+ config.assoc_abbreviations = ransack_abbreviations["associations"] if ransack_abbreviations["associations"]
21
+ end
22
+
23
+ require "ransack_abbreviator/ransack_extensions/nodes/condition"
24
+ require "ransack_abbreviator/ransack_extensions/nodes/grouping"
25
+ require "ransack_abbreviator/ransack_extensions/context"
26
+ require "ransack_abbreviator/ransack_extensions/search"
27
+ require 'ransack_abbreviator/adapters/active_record'
28
+ require "ransack_abbreviator/view_helpers"
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "ransack_abbreviator/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "ransack_abbreviator"
7
+ s.version = RansackAbbreviator::VERSION
8
+ s.authors = ["Jamie Davidson"]
9
+ s.email = ["jhdavids8@gmail.com"]
10
+ s.homepage = "https://github.com/jhdavids8/ransack-abbreviator"
11
+ s.summary = "Avoid POSTs. Abbreviate those Ransack queries."
12
+ s.description = "Avoid POSTs. Abbreviate those Ransack queries."
13
+
14
+ s.rubyforge_project = "ransack_abbreviator"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_dependency 'ransack', '~> 0.7'
22
+ s.add_development_dependency "pry"
23
+ s.add_development_dependency 'rspec', '~> 2.8.0'
24
+ s.add_development_dependency 'machinist', '~> 1.0.6'
25
+ s.add_development_dependency 'faker', '~> 0.9.5'
26
+ s.add_development_dependency 'sqlite3', '~> 1.3.3'
27
+ end
@@ -0,0 +1,5 @@
1
+ Article.blueprint do
2
+ person
3
+ title
4
+ body
5
+ end
@@ -0,0 +1,5 @@
1
+ Comment.blueprint do
2
+ article
3
+ person
4
+ body
5
+ end
@@ -0,0 +1,3 @@
1
+ Note.blueprint do
2
+ note
3
+ end
@@ -0,0 +1,5 @@
1
+ Person.blueprint do
2
+ name
3
+ middle_name
4
+ salary
5
+ end
@@ -0,0 +1,3 @@
1
+ Tag.blueprint do
2
+ name { Sham.tag_name }
3
+ end
@@ -0,0 +1,85 @@
1
+ require 'spec_helper'
2
+
3
+ module RansackAbbreviator
4
+ module Adapters
5
+ module ActiveRecord
6
+ describe Base do
7
+ subject { ::ActiveRecord::Base }
8
+
9
+ describe '#ransackable_column_abbreviations' do
10
+ subject { Person.ransackable_column_abbreviations }
11
+
12
+ it { should include 'name' => 'nm' }
13
+ it { should include 'middle_name' => 'mn' }
14
+ end
15
+
16
+ describe '#ransackable_assoc_abbreviations' do
17
+ subject { Person.ransackable_assoc_abbreviations }
18
+
19
+ it { should include 'children' => 'ch' }
20
+ it { should include 'parent' => 'pa' }
21
+ end
22
+
23
+ describe '#ransackable_column_name_for' do
24
+ context 'when a defined abbreviation' do
25
+ it "returns the full column name" do
26
+ Person.ransackable_column_name_for("nm").should eq "name"
27
+ Person.ransackable_column_name_for("mn").should eq "middle_name"
28
+ end
29
+ end
30
+
31
+ context 'when an undefined abbreviation' do
32
+ it "returns nil" do
33
+ Person.ransackable_column_name_for("you_fake").should be_nil
34
+ end
35
+ end
36
+ end
37
+
38
+ describe '#ransackable_column_abbr_for' do
39
+ context 'when a defined column' do
40
+ it "returns the abbreviation" do
41
+ Person.ransackable_column_abbr_for("name").should eq "nm"
42
+ Person.ransackable_column_abbr_for("middle_name").should eq "mn"
43
+ end
44
+ end
45
+
46
+ context 'when an undefined column' do
47
+ it "returns the passed-in column" do
48
+ Person.ransackable_column_abbr_for("you_fake").should eq "you_fake"
49
+ end
50
+ end
51
+ end
52
+
53
+ describe '#ransackable_assoc_name_for' do
54
+ context 'when a defined abbreviation' do
55
+ it "returns the full association name" do
56
+ Person.ransackable_assoc_name_for("ch").should eq "children"
57
+ Person.ransackable_assoc_name_for("pa").should eq "parent"
58
+ end
59
+ end
60
+
61
+ context 'when an undefined abbreviation' do
62
+ it "returns nil" do
63
+ Person.ransackable_assoc_name_for("you_fake").should be_nil
64
+ end
65
+ end
66
+ end
67
+
68
+ describe '#ransackable_assoc_abbr_for' do
69
+ context 'when a defined association' do
70
+ it "returns the abbreviation" do
71
+ Person.ransackable_assoc_abbr_for("children").should eq "ch"
72
+ Person.ransackable_assoc_abbr_for("parent").should eq "pa"
73
+ end
74
+ end
75
+
76
+ context 'when an undefined association' do
77
+ it "returns the passed-in association" do
78
+ Person.ransackable_assoc_abbr_for("you_fake").should eq "you_fake"
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,14 @@
1
+ require "spec_helper"
2
+
3
+ module RansackAbbreviator
4
+ describe Configuration do
5
+ context "parsing a config.yml" do
6
+ it "initializes the abbreviations" do
7
+ RansackAbbreviator.column_abbreviations.should_not be_blank
8
+ RansackAbbreviator.column_abbreviations["name"].should == "nm"
9
+ RansackAbbreviator.assoc_abbreviations.should_not be_blank
10
+ RansackAbbreviator.assoc_abbreviations[:authored_article_comments].should == "a_ac"
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,90 @@
1
+ require 'spec_helper'
2
+
3
+ module RansackAbbreviator
4
+ module ViewHelpers
5
+ describe "#ransack_abbreviation_for" do
6
+ context "a lookup of a defined column" do
7
+ it "returns an abbreviated column name" do
8
+ search = Ransack::Search.new(Person)
9
+ ransack_abbreviation_for(search, :name_eq).should == "nm_eq"
10
+ ransack_abbreviation_for(search, :middle_name_eq).should == "mn_eq"
11
+ end
12
+ end
13
+
14
+ context "a lookup of an undefined column" do
15
+ it "returns the full column name" do
16
+ search = Ransack::Search.new(Person)
17
+ ransack_abbreviation_for(search, :salary_eq).should == "salary_eq"
18
+ end
19
+ end
20
+
21
+ context "a lookup of a defined association" do
22
+ context "a lookup of a defined column" do
23
+ it "returns an abbreviated assoc & column pair" do
24
+ search = Ransack::Search.new(Article)
25
+ ransack_abbreviation_for(search, :person_name_eq).should == "pr.nm_eq"
26
+ ransack_abbreviation_for(search, :person_middle_name_eq).should == "pr.mn_eq"
27
+ search = Ransack::Search.new(Person)
28
+ ransack_abbreviation_for(search, :authored_article_comments_vote_count_lteq).should == "a_ac.vc_lteq"
29
+ end
30
+ end
31
+
32
+ context "a lookup of an undefined column" do
33
+ it "returns an abbreviated table but full column" do
34
+ search = Ransack::Search.new(Article)
35
+ ransack_abbreviation_for(search, :person_salary_eq).should == "pr.salary_eq"
36
+ end
37
+ end
38
+ end
39
+
40
+ context "a lookup of an undefined association" do
41
+ context "a lookup of a defined column" do
42
+ it "returns the full association but abbreviated column" do
43
+ search = Ransack::Search.new(Person)
44
+ ransack_abbreviation_for(search, :articles_title_cont).should == "articles.tl_cont"
45
+ end
46
+ end
47
+
48
+ context "a lookup of an undefined column" do
49
+ it "returns a full association & column pair" do
50
+ search = Ransack::Search.new(Person)
51
+ ransack_abbreviation_for(search, :articles_body_cont).should == "articles.body_cont"
52
+ end
53
+ end
54
+ end
55
+
56
+ context "a lookup of a multi-condition string" do
57
+ it "returns abbreviated forms for all conditions" do
58
+ search = Ransack::Search.new(Person)
59
+ ransack_abbreviation_for(search, :children_name_or_children_salary_eq).should == "ch.nm_or_ch.salary_eq"
60
+ end
61
+ end
62
+
63
+ context "a lookup of a defined polymorphic belongs_to association" do
64
+ it "returns the abbreviated name for the polymorphic association" do
65
+ search = Ransack::Search.new(Note)
66
+ ransack_abbreviation_for(search, :notable_of_Person_type_name_eq).should == "nbl_of_pr_type.nm_eq"
67
+ end
68
+ end
69
+
70
+ context "a lookup of a nested condition" do
71
+ it "abbreviates each association and column" do
72
+ search = Ransack::Search.new(Person)
73
+ ransack_abbreviation_for(search, :articles_comments_body_cont).should == "articles_cm.body_cont"
74
+ end
75
+
76
+ it "abbreviates nested conditions for polymorphic associations" do
77
+ search = Ransack::Search.new(Note)
78
+ ransack_abbreviation_for(search, :notable_of_Person_type_children_name_eq).should == "nbl_of_pr_type_ch.nm_eq"
79
+ end
80
+ end
81
+
82
+ context "a lookup of something totally random" do
83
+ it "does absolutely nothing" do
84
+ search = Ransack::Search.new(Note)
85
+ ransack_abbreviation_for(search, :i_am_garbage).should == "i_am_garbage"
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,379 @@
1
+ require "spec_helper"
2
+
3
+ module Ransack # We're testing Ransack's Search wih abbreviations
4
+ describe Search do
5
+ describe '#build' do
6
+ context "with abbreviations" do
7
+ it 'creates Conditions for top-level attributes' do
8
+ search = Search.new(Person)
9
+ search.build(ransack_abbreviation_for(search, :name_eq) => 'Ernie')
10
+ condition = search.base[:name_eq]
11
+ condition.should be_a Nodes::Condition
12
+ condition.predicate.name.should eq 'eq'
13
+ condition.attributes.first.name.should eq 'name'
14
+ condition.value.should eq 'Ernie'
15
+ end
16
+
17
+ it 'creates Conditions for association attributes' do
18
+ search = Search.new(Person)
19
+ search.build(ransack_abbreviation_for(search, :children_name_eq) => 'Ernie')
20
+ condition = search.base[:children_name_eq]
21
+ condition.should be_a Nodes::Condition
22
+ condition.predicate.name.should eq 'eq'
23
+ condition.attributes.first.name.should eq 'children_name'
24
+ condition.value.should eq 'Ernie'
25
+ end
26
+
27
+ it 'creates Conditions for polymorphic belongs_to association attributes' do
28
+ search = Search.new(Note)
29
+ search.build(ransack_abbreviation_for(search, :notable_of_Person_type_name_eq) => 'Ernie')
30
+ condition = search.base[:notable_of_Person_type_name_eq]
31
+ condition.should be_a Nodes::Condition
32
+ condition.predicate.name.should eq 'eq'
33
+ condition.attributes.first.name.should eq 'notable_of_Person_type_name'
34
+ condition.value.should eq 'Ernie'
35
+ end
36
+
37
+ it 'creates Conditions for multiple polymorphic belongs_to association attributes' do
38
+ search = Search.new(Note)
39
+ search.build(ransack_abbreviation_for(search, :notable_of_Person_type_name_or_notable_of_Article_type_title_eq) => 'Ernie')
40
+ condition = search.base[:notable_of_Person_type_name_or_notable_of_Article_type_title_eq]
41
+ condition.should be_a Nodes::Condition
42
+ condition.predicate.name.should eq 'eq'
43
+ condition.attributes.first.name.should eq 'notable_of_Person_type_name'
44
+ condition.attributes.last.name.should eq 'notable_of_Article_type_title'
45
+ condition.value.should eq 'Ernie'
46
+ end
47
+
48
+ it 'discards empty conditions' do
49
+ search = Search.new(Person)
50
+ search.build(ransack_abbreviation_for(search, :children_name_eq) => '')
51
+ condition = search.base[:children_name_eq]
52
+ condition.should be_nil
53
+ end
54
+
55
+ it 'accepts arrays of groupings' do
56
+ search = Search.new(Person)
57
+ search.build(
58
+ :g => [
59
+ ransack_abbreviations_for(search, :m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie'),
60
+ ransack_abbreviations_for(search, :m => 'or', :name_eq => 'Bert', :children_name_eq => 'Bert')
61
+ ]
62
+ )
63
+ ors = search.groupings
64
+ ors.should have(2).items
65
+ or1, or2 = ors
66
+ or1.should be_a Nodes::Grouping
67
+ or1.combinator.should eq 'or'
68
+ or2.should be_a Nodes::Grouping
69
+ or2.combinator.should eq 'or'
70
+ end
71
+
72
+ it 'accepts "attributes" hashes for groupings' do
73
+ search = Search.new(Person)
74
+ search.build(
75
+ :g => {
76
+ '0' => ransack_abbreviations_for(search, :m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie'),
77
+ '1' => ransack_abbreviations_for(search, :m => 'or', :name_eq => 'Bert', :children_name_eq => 'Bert'),
78
+ }
79
+ )
80
+ ors = search.groupings
81
+ ors.should have(2).items
82
+ or1, or2 = ors
83
+ or1.should be_a Nodes::Grouping
84
+ or1.combinator.should eq 'or'
85
+ or2.should be_a Nodes::Grouping
86
+ or2.combinator.should eq 'or'
87
+ end
88
+
89
+ it 'accepts "attributes" hashes for conditions' do
90
+ search = Search.new(Person)
91
+ search.build(
92
+ :c => {
93
+ '0' => {:a => ransack_abbreviations_for(search, ['name']), :p => 'eq', :v => ['Ernie']},
94
+ '1' => {:a => ransack_abbreviations_for(search, ['children_name', 'parent_name']), :p => 'eq', :v => ['Ernie'], :m => 'or'}
95
+ }
96
+ )
97
+ conditions = search.base.conditions
98
+ conditions.should have(2).items
99
+ conditions.map {|c| c.class}.should eq [Nodes::Condition, Nodes::Condition]
100
+ end
101
+
102
+ it 'creates Conditions for custom predicates that take arrays' do
103
+ Ransack.configure do |config|
104
+ config.add_predicate 'ary_pred',
105
+ :wants_array => true
106
+ end
107
+
108
+ search = Search.new(Person)
109
+ search.build(ransack_abbreviation_for(search, :name_ary_pred) => ['Ernie', 'Bert'])
110
+ condition = search.base[:name_ary_pred]
111
+ condition.should be_a Nodes::Condition
112
+ condition.predicate.name.should eq 'ary_pred'
113
+ condition.attributes.first.name.should eq 'name'
114
+ condition.value.should eq ['Ernie', 'Bert']
115
+ end
116
+
117
+ it 'does not evaluate the query on #inspect' do
118
+ search = Search.new(Person)
119
+ search.build(ransack_abbreviation_for(search, :children_id_in) => [1, 2, 3])
120
+ search.inspect.should_not match /ActiveRecord/
121
+ end
122
+ end
123
+ end
124
+
125
+ context "without abbreviations" do
126
+ it 'creates Conditions for top-level attributes' do
127
+ search = Search.new(Person, :name_eq => 'Ernie')
128
+ condition = search.base[:name_eq]
129
+ condition.should be_a Nodes::Condition
130
+ condition.predicate.name.should eq 'eq'
131
+ condition.attributes.first.name.should eq 'name'
132
+ condition.value.should eq 'Ernie'
133
+ end
134
+
135
+ it 'creates Conditions for association attributes' do
136
+ search = Search.new(Person, :children_name_eq => 'Ernie')
137
+ condition = search.base[:children_name_eq]
138
+ condition.should be_a Nodes::Condition
139
+ condition.predicate.name.should eq 'eq'
140
+ condition.attributes.first.name.should eq 'children_name'
141
+ condition.value.should eq 'Ernie'
142
+ end
143
+
144
+ it 'creates Conditions for polymorphic belongs_to association attributes' do
145
+ search = Search.new(Note, :notable_of_Person_type_name_eq => 'Ernie')
146
+ condition = search.base[:notable_of_Person_type_name_eq]
147
+ condition.should be_a Nodes::Condition
148
+ condition.predicate.name.should eq 'eq'
149
+ condition.attributes.first.name.should eq 'notable_of_Person_type_name'
150
+ condition.value.should eq 'Ernie'
151
+ end
152
+
153
+ it 'creates Conditions for multiple polymorphic belongs_to association attributes' do
154
+ search = Search.new(Note, :notable_of_Person_type_name_or_notable_of_Article_type_title_eq => 'Ernie')
155
+ condition = search.base[:notable_of_Person_type_name_or_notable_of_Article_type_title_eq]
156
+ condition.should be_a Nodes::Condition
157
+ condition.predicate.name.should eq 'eq'
158
+ condition.attributes.first.name.should eq 'notable_of_Person_type_name'
159
+ condition.attributes.last.name.should eq 'notable_of_Article_type_title'
160
+ condition.value.should eq 'Ernie'
161
+ end
162
+
163
+ it 'discards empty conditions' do
164
+ search = Search.new(Person, :children_name_eq => '')
165
+ condition = search.base[:children_name_eq]
166
+ condition.should be_nil
167
+ end
168
+
169
+ it 'accepts arrays of groupings' do
170
+ search = Search.new(Person,
171
+ :g => [
172
+ {:m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie'},
173
+ {:m => 'or', :name_eq => 'Bert', :children_name_eq => 'Bert'},
174
+ ]
175
+ )
176
+ ors = search.groupings
177
+ ors.should have(2).items
178
+ or1, or2 = ors
179
+ or1.should be_a Nodes::Grouping
180
+ or1.combinator.should eq 'or'
181
+ or2.should be_a Nodes::Grouping
182
+ or2.combinator.should eq 'or'
183
+ end
184
+
185
+ it 'accepts "attributes" hashes for groupings' do
186
+ search = Search.new(Person,
187
+ :g => {
188
+ '0' => {:m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie'},
189
+ '1' => {:m => 'or', :name_eq => 'Bert', :children_name_eq => 'Bert'},
190
+ }
191
+ )
192
+ ors = search.groupings
193
+ ors.should have(2).items
194
+ or1, or2 = ors
195
+ or1.should be_a Nodes::Grouping
196
+ or1.combinator.should eq 'or'
197
+ or2.should be_a Nodes::Grouping
198
+ or2.combinator.should eq 'or'
199
+ end
200
+
201
+ it 'accepts "attributes" hashes for conditions' do
202
+ search = Search.new(Person,
203
+ :c => {
204
+ '0' => {:a => ['name'], :p => 'eq', :v => ['Ernie']},
205
+ '1' => {:a => ['children_name', 'parent_name'], :p => 'eq', :v => ['Ernie'], :m => 'or'}
206
+ }
207
+ )
208
+ conditions = search.base.conditions
209
+ conditions.should have(2).items
210
+ conditions.map {|c| c.class}.should eq [Nodes::Condition, Nodes::Condition]
211
+ end
212
+
213
+ it 'creates Conditions for custom predicates that take arrays' do
214
+ Ransack.configure do |config|
215
+ config.add_predicate 'ary_pred',
216
+ :wants_array => true
217
+ end
218
+
219
+ search = Search.new(Person, :name_ary_pred => ['Ernie', 'Bert'])
220
+ condition = search.base[:name_ary_pred]
221
+ condition.should be_a Nodes::Condition
222
+ condition.predicate.name.should eq 'ary_pred'
223
+ condition.attributes.first.name.should eq 'name'
224
+ condition.value.should eq ['Ernie', 'Bert']
225
+ end
226
+
227
+ it 'does not evaluate the query on #inspect' do
228
+ search = Search.new(Person, :children_id_in => [1, 2, 3])
229
+ search.inspect.should_not match /ActiveRecord/
230
+ end
231
+ end
232
+
233
+ describe '#result' do
234
+ context "with abbreviations" do
235
+ it "evaluates a basic condition" do
236
+ search = Search.new(Person)
237
+ search.build(ransack_abbreviation_for(search, :name_eq) => 'Ernie')
238
+ search.result.should be_an ActiveRecord::Relation
239
+ where = search.result.where_values.first
240
+ where.to_sql.should match /"people"\."name" = 'Ernie'/
241
+ end
242
+
243
+ it 'evaluates conditions contextually' do
244
+ search = Search.new(Person)
245
+ search.build(ransack_abbreviation_for(search, :children_name_eq) => 'Ernie')
246
+ search.result.should be_an ActiveRecord::Relation
247
+ where = search.result.where_values.first
248
+ where.to_sql.should match /"children_people"\."name" = 'Ernie'/
249
+ end
250
+
251
+ it 'evaluates polymorphic belongs_to association conditions contextually' do
252
+ search = Search.new(Note)
253
+ search.build(ransack_abbreviation_for(search, :notable_of_Person_type_name_eq) => 'Ernie')
254
+ search.result.should be_an ActiveRecord::Relation
255
+ where = search.result.where_values.first
256
+ where.to_sql.should match /"people"."name" = 'Ernie'/
257
+ end
258
+
259
+ it 'evaluates nested conditions' do
260
+ search = Search.new(Person)
261
+ search.build(
262
+ ransack_abbreviation_for(search, :children_name_eq) => 'Ernie',
263
+ :g => [
264
+ ransack_abbreviations_for(search, :m => 'or', :name_eq => 'Ernie', :children_children_name_eq => 'Ernie')
265
+ ]
266
+ )
267
+ search.result.should be_an ActiveRecord::Relation
268
+ where = search.result.where_values.first
269
+ where.to_sql.should match /"children_people"."name" = 'Ernie'/
270
+ where.to_sql.should match /"people"."name" = 'Ernie'/
271
+ where.to_sql.should match /"children_people_2"."name" = 'Ernie'/
272
+ end
273
+
274
+ it 'evaluates arrays of groupings' do
275
+ search = Search.new(Person)
276
+ search.build(
277
+ :g => [
278
+ ransack_abbreviations_for(search, :m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie'),
279
+ ransack_abbreviations_for(search, :m => 'or', :name_eq => 'Bert', :children_name_eq => 'Bert'),
280
+ ]
281
+ )
282
+ search.result.should be_an ActiveRecord::Relation
283
+ where = search.result.where_values.first
284
+ sql = where.to_sql
285
+ first, second = sql.split(/ AND /)
286
+ first.should match /"people"."name" = 'Ernie'/
287
+ first.should match /"children_people"."name" = 'Ernie'/
288
+ second.should match /"people"."name" = 'Bert'/
289
+ second.should match /"children_people"."name" = 'Bert'/
290
+ end
291
+
292
+ it 'returns distinct records when passed :distinct => true' do
293
+ search = Search.new(Person)
294
+ search.build(
295
+ :g => [ransack_abbreviations_for(search, :m => 'or', :comments_body_cont => 'e', :articles_comments_body_cont => 'e')]
296
+ )
297
+ search.result.all.should have(920).items
298
+ search.result(:distinct => true).should have(330).items
299
+ search.result.all.uniq.should eq search.result(:distinct => true).all
300
+ end
301
+ end
302
+
303
+ context "without abbreviations" do
304
+ it 'evaluates conditions contextually' do
305
+ search = Search.new(Person, :children_name_eq => 'Ernie')
306
+ search.result.should be_an ActiveRecord::Relation
307
+ where = search.result.where_values.first
308
+ where.to_sql.should match /"children_people"\."name" = 'Ernie'/
309
+ end
310
+
311
+ it 'evaluates compound conditions contextually' do
312
+ search = Search.new(Person, :children_name_or_name_eq => 'Ernie')
313
+ search.result.should be_an ActiveRecord::Relation
314
+ where = search.result.where_values.first
315
+ where.to_sql.should match /"children_people"\."name" = 'Ernie' OR "people"\."name" = 'Ernie'/
316
+ end
317
+
318
+ it 'evaluates polymorphic belongs_to association conditions contextually' do
319
+ search = Search.new(Note, :notable_of_Person_type_name_eq => 'Ernie')
320
+ search.result.should be_an ActiveRecord::Relation
321
+ where = search.result.where_values.first
322
+ where.to_sql.should match /"people"."name" = 'Ernie'/
323
+ end
324
+
325
+ it 'evaluates nested conditions' do
326
+ search = Search.new(Person, :children_name_eq => 'Ernie',
327
+ :g => [{
328
+ :m => 'or',
329
+ :name_eq => 'Ernie',
330
+ :children_children_name_eq => 'Ernie'
331
+ }]
332
+ )
333
+ search.result.should be_an ActiveRecord::Relation
334
+ where = search.result.where_values.first
335
+ where.to_sql.should match /"children_people"."name" = 'Ernie'/
336
+ where.to_sql.should match /"people"."name" = 'Ernie'/
337
+ where.to_sql.should match /"children_people_2"."name" = 'Ernie'/
338
+ end
339
+
340
+ it 'evaluates arrays of groupings' do
341
+ search = Search.new(Person,
342
+ :g => [
343
+ {:m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie'},
344
+ {:m => 'or', :name_eq => 'Bert', :children_name_eq => 'Bert'},
345
+ ]
346
+ )
347
+ search.result.should be_an ActiveRecord::Relation
348
+ where = search.result.where_values.first
349
+ sql = where.to_sql
350
+ first, second = sql.split(/ AND /)
351
+ first.should match /"people"."name" = 'Ernie'/
352
+ first.should match /"children_people"."name" = 'Ernie'/
353
+ second.should match /"people"."name" = 'Bert'/
354
+ second.should match /"children_people"."name" = 'Bert'/
355
+ end
356
+
357
+ it 'returns distinct records when passed :distinct => true' do
358
+ search = Search.new(Person, :g => [{:m => 'or', :comments_body_cont => 'e', :articles_comments_body_cont => 'e'}])
359
+ search.result.all.should have(920).items
360
+ search.result(:distinct => true).should have(330).items
361
+ search.result.all.uniq.should eq search.result(:distinct => true).all
362
+ end
363
+ end
364
+
365
+ it "has the same results for a query with and without abbreviations" do
366
+ # Just some random sanity checks
367
+ search = Search.new(Person, :authored_article_comments_vote_count_lteq => 10)
368
+ abbr_search = Search.new(Person)
369
+ abbr_search.build(ransack_abbreviation_for(abbr_search, :authored_article_comments_vote_count_lteq) => 10)
370
+ search.result.where_values.first.to_sql.should eq abbr_search.result.where_values.first.to_sql
371
+
372
+ search = Search.new(Note, :notable_of_Person_type_children_name_eq => "Ernie")
373
+ abbr_search = Search.new(Note)
374
+ abbr_search.build(ransack_abbreviation_for(abbr_search, :notable_of_Person_type_children_name_eq) => "Ernie")
375
+ search.result.where_values.first.to_sql.should eq abbr_search.result.where_values.first.to_sql
376
+ end
377
+ end
378
+ end
379
+ end