ransack_abbreviator 0.0.1

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.
@@ -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