lazy-searchlogic 2.4.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,66 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe "Or conditions" do
4
+ it "should define a scope by the exact same name as requested by the code" do
5
+ User.name_or_username_like('Test')
6
+ User.respond_to?(:name_or_username_like).should be_true
7
+ end
8
+
9
+ it "should match username or name" do
10
+ User.username_or_name_like("ben").proxy_options.should == {:conditions => "(users.username LIKE '%ben%') OR (users.name LIKE '%ben%')"}
11
+ end
12
+
13
+ it "should use the specified condition" do
14
+ User.username_begins_with_or_name_like("ben").proxy_options.should == {:conditions => "(users.username LIKE 'ben%') OR (users.name LIKE '%ben%')"}
15
+ end
16
+
17
+ it "should use the last specified condition" do
18
+ User.username_or_name_like_or_id_or_age_lt(10).proxy_options.should == {:conditions => "(users.username LIKE '%10%') OR (users.name LIKE '%10%') OR (users.id < 10) OR (users.age < 10)"}
19
+ end
20
+
21
+ it "should raise an error on unknown conditions" do
22
+ lambda { User.usernme_begins_with_or_name_like("ben") }.should raise_error(Searchlogic::NamedScopes::OrConditions::UnknownConditionError)
23
+ end
24
+
25
+ it "should work well with _or_equal_to" do
26
+ User.id_less_than_or_equal_to_or_age_gt(10).proxy_options.should == {:conditions => "(users.id <= 10) OR (users.age > 10)"}
27
+ end
28
+
29
+ it "should work well with _or_equal_to_any" do
30
+ User.id_less_than_or_equal_to_all_or_age_gt(10).proxy_options.should == {:conditions => "(users.id <= 10) OR (users.age > 10)"}
31
+ end
32
+
33
+ it "should work well with _or_equal_to_all" do
34
+ User.id_less_than_or_equal_to_any_or_age_gt(10).proxy_options.should == {:conditions => "(users.id <= 10) OR (users.age > 10)"}
35
+ end
36
+
37
+ it "should play nice with other scopes" do
38
+ User.username_begins_with("ben").id_gt(10).age_not_nil.username_or_name_ends_with("ben").scope(:find).should ==
39
+ {:conditions => "((users.username LIKE '%ben') OR (users.name LIKE '%ben')) AND ((users.age IS NOT NULL) AND ((users.id > 10) AND (users.username LIKE 'ben%')))"}
40
+ end
41
+
42
+ it "should play nice with scopes on associations" do
43
+ lambda { User.name_or_company_name_like("ben") }.should_not raise_error(Searchlogic::NamedScopes::OrConditions::NoConditionSpecifiedError)
44
+ User.name_or_company_name_like("ben").proxy_options.should == {:joins => :company, :conditions => "(users.name LIKE '%ben%') OR (companies.name LIKE '%ben%')"}
45
+ User.company_name_or_name_like("ben").proxy_options.should == {:joins => :company, :conditions => "(companies.name LIKE '%ben%') OR (users.name LIKE '%ben%')"}
46
+ User.company_name_or_company_description_like("ben").proxy_options.should == {:joins =>[:company], :conditions => "(companies.name LIKE '%ben%') OR (companies.description LIKE '%ben%')"}
47
+ end
48
+
49
+ it "should not get confused by the 'or' in find_or_create_by_* methods" do
50
+ User.create(:name => "Fred")
51
+ User.find_or_create_by_name("Fred").should be_a_kind_of User
52
+ end
53
+
54
+ it "should not get confused by the 'or' in compound find_or_create_by_* methods" do
55
+ User.create(:name => "Fred", :username => "fredb")
56
+ User.find_or_create_by_name_and_username("Fred", "fredb").should be_a_kind_of User
57
+ end
58
+
59
+ it "should work with User.search(conditions) method" do
60
+ User.search(:username_or_name_like => 'ben').proxy_options.should == {:conditions => "(users.username LIKE '%ben%') OR (users.name LIKE '%ben%')"}
61
+ end
62
+
63
+ it "should convert types properly when used with User.search(conditions) method" do
64
+ User.search(:id_or_age_lte => '10').proxy_options.should == {:conditions => "(users.id <= 10) OR (users.age <= 10)"}
65
+ end
66
+ end
@@ -0,0 +1,34 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe "Ordering" do
4
+ it "should be dynamically created and then cached" do
5
+ User.should_not respond_to(:ascend_by_username)
6
+ User.ascend_by_username
7
+ User.should respond_to(:ascend_by_username)
8
+ end
9
+
10
+ it "should have ascending" do
11
+ %w(bjohnson thunt).each { |username| User.create(:username => username) }
12
+ User.ascend_by_username.all.should == User.all(:order => "username ASC")
13
+ end
14
+
15
+ it "should have descending" do
16
+ %w(bjohnson thunt).each { |username| User.create(:username => username) }
17
+ User.descend_by_username.all.should == User.all(:order => "username DESC")
18
+ end
19
+
20
+ it "should have order" do
21
+ User.order("ascend_by_username").proxy_options.should == User.ascend_by_username.proxy_options
22
+ end
23
+
24
+ it "should have order by custom scope" do
25
+ User.column_names.should_not include("custom")
26
+ %w(bjohnson thunt fisons).each { |username| User.create(:username => username) }
27
+ User.named_scope(:ascend_by_custom, :order => "username ASC, name DESC")
28
+ User.order("ascend_by_custom").proxy_options.should == User.ascend_by_custom.proxy_options
29
+ end
30
+
31
+ it "should have priorty to columns over conflicting association columns" do
32
+ Company.ascend_by_users_count
33
+ end
34
+ end
@@ -0,0 +1,416 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
2
+
3
+ describe "Search" do
4
+ context "implementation" do
5
+ it "should create a search proxy" do
6
+ User.search(:username => "joe").should be_kind_of(Searchlogic::Search)
7
+ end
8
+
9
+ it "should create a search proxy using the same class" do
10
+ User.search.klass.should == User
11
+ end
12
+
13
+ it "should pass on the current scope to the proxy" do
14
+ company = Company.create
15
+ user = company.users.create
16
+ search = company.users.search
17
+ search.current_scope.should == company.users.scope(:find)
18
+ end
19
+ end
20
+
21
+ context "initialization" do
22
+ it "should require a class" do
23
+ lambda { Searchlogic::Search.new }.should raise_error(ArgumentError)
24
+ end
25
+
26
+ it "should set the conditions" do
27
+ search = User.search(:username => "bjohnson")
28
+ search.conditions.should == {:username => "bjohnson"}
29
+ end
30
+ end
31
+
32
+ it "should clone properly" do
33
+ company = Company.create
34
+ user1 = company.users.create(:age => 5)
35
+ user2 = company.users.create(:age => 25)
36
+ search1 = company.users.search(:age_gt => 10)
37
+ search2 = search1.clone
38
+ search2.age_gt = 1
39
+ search2.all.should == User.all
40
+ search1.all.should == [user2]
41
+ end
42
+
43
+ it "should clone properly without scope" do
44
+ user1 = User.create(:age => 5)
45
+ user2 = User.create(:age => 25)
46
+ search1 = User.search(:age_gt => 10)
47
+ search2 = search1.clone
48
+ search2.age_gt = 1
49
+ search2.all.should == User.all
50
+ search1.all.should == [user2]
51
+ end
52
+
53
+ it "should delete the condition" do
54
+ search = User.search(:username_like => "bjohnson")
55
+ search.delete("username_like")
56
+ search.username_like.should be_nil
57
+ end
58
+
59
+ context "conditions" do
60
+ it "should set the conditions and be accessible individually" do
61
+ search = User.search
62
+ search.conditions = {:username => "bjohnson"}
63
+ search.username.should == "bjohnson"
64
+ end
65
+
66
+ it "should set the conditions and allow string keys" do
67
+ search = User.search
68
+ search.conditions = {"username" => "bjohnson"}
69
+ search.username.should == "bjohnson"
70
+ end
71
+
72
+ it "should use custom scopes before normalizing" do
73
+ User.create(:username => "bjohnson")
74
+ User.named_scope :username, lambda { |value| {:conditions => {:username => value.reverse}} }
75
+ search1 = User.search(:username => "bjohnson")
76
+ search2 = User.search(:username => "nosnhojb")
77
+ search1.count.should == 0
78
+ search2.count.should == 1
79
+ end
80
+
81
+ # We ignore them upon execution. But we still want to accept the condition so that returning the conditions
82
+ # preserves the values.
83
+ it "should ignore blank values but still return on conditions" do
84
+ search = User.search
85
+ search.conditions = {"username" => ""}
86
+ search.username.should be_nil
87
+ search.conditions.should == {:username => ""}
88
+ end
89
+
90
+ it "should not ignore blank values and should not cast them" do
91
+ search = User.search
92
+ search.conditions = {"id_equals" => ""}
93
+ search.id_equals.should be_nil
94
+ search.conditions.should == {:id_equals => ""}
95
+ end
96
+
97
+ it "should ignore blank values in arrays" do
98
+ search = User.search
99
+ search.conditions = {"username_equals_any" => [""]}
100
+ search.username_equals_any.should be_nil
101
+
102
+ search.conditions = {"id_equals_any" => ["", "1"]}
103
+ search.id_equals_any.should == [1]
104
+ end
105
+ end
106
+
107
+ context "condition accessors" do
108
+ it "should allow setting exact columns individually" do
109
+ search = User.search
110
+ search.username = "bjohnson"
111
+ search.username.should == "bjohnson"
112
+ end
113
+
114
+ it "should allow setting local column conditions individually" do
115
+ search = User.search
116
+ search.username_gt = "bjohnson"
117
+ search.username_gt.should == "bjohnson"
118
+ end
119
+
120
+ it "should allow chaining conditions" do
121
+ user = User.create(:username => "bjohnson", :age => 20)
122
+ User.create(:username => "bjohnson", :age => 5)
123
+ search = User.search
124
+ search.username_equals("bjohnson").age_gt(10)
125
+ search.all.should == [user]
126
+ end
127
+
128
+ it "should allow setting association conditions" do
129
+ search = User.search
130
+ search.orders_total_gt = 10
131
+ search.orders_total_gt.should == 10
132
+ end
133
+
134
+ it "should allow setting pre-existing association conditions" do
135
+ User.named_scope :uname, lambda { |value| {:conditions => ["users.username = ?", value]} }
136
+ search = Company.search
137
+ search.users_uname = "bjohnson"
138
+ search.users_uname.should == "bjohnson"
139
+ end
140
+
141
+ it "should allow setting pre-existing association alias conditions" do
142
+ User.alias_scope :username_has, lambda { |value| User.username_like(value) }
143
+ search = Company.search
144
+ search.users_username_has = "bjohnson"
145
+ search.users_username_has.should == "bjohnson"
146
+ end
147
+
148
+ it "should allow using custom conditions" do
149
+ User.named_scope(:four_year_olds, { :conditions => { :age => 4 } })
150
+ search = User.search
151
+ search.four_year_olds = true
152
+ search.four_year_olds.should == true
153
+ search.proxy_options.should == User.four_year_olds.proxy_options
154
+ end
155
+
156
+ it "should not merge conflicting conditions into one value" do
157
+ # This class should JUST be a proxy. It should not do anything more than that.
158
+ # A user would be allowed to call both named scopes if they wanted.
159
+ search = User.search
160
+ search.username_greater_than = "bjohnson1"
161
+ search.username_gt = "bjohnson2"
162
+ search.username_greater_than.should == "bjohnson1"
163
+ search.username_gt.should == "bjohnson2"
164
+ end
165
+
166
+ it "should allow setting custom conditions individually with an arity of 0" do
167
+ User.named_scope(:four_year_olds, :conditions => {:age => 4})
168
+ search = User.search
169
+ search.four_year_olds = true
170
+ search.four_year_olds.should == true
171
+ end
172
+
173
+ it "should allow setting custom conditions individually with an arity of 1" do
174
+ User.named_scope(:username_should_be, lambda { |u| {:conditions => {:username => u}} })
175
+ search = User.search
176
+ search.username_should_be = "bjohnson"
177
+ search.username_should_be.should == "bjohnson"
178
+ end
179
+
180
+ it "should not allow setting conditions that are not scopes" do
181
+ search = User.search
182
+ lambda { search.unknown = true }.should raise_error(Searchlogic::Search::UnknownConditionError)
183
+ end
184
+
185
+ it "should not allow setting conditions on sensitive methods" do
186
+ search = User.search
187
+ lambda { search.destroy = true }.should raise_error(Searchlogic::Search::UnknownConditionError)
188
+ end
189
+
190
+ it "should not use the ruby implementation of the id method" do
191
+ search = User.search
192
+ search.id.should be_nil
193
+ end
194
+
195
+ context "type casting" do
196
+ it "should be a Boolean given true" do
197
+ search = User.search
198
+ search.id_nil = true
199
+ search.id_nil.should == true
200
+ end
201
+
202
+ it "should be a Boolean given 'true'" do
203
+ search = User.search
204
+ search.id_nil = "true"
205
+ search.id_nil.should == true
206
+ end
207
+
208
+ it "should be a Boolean given '1'" do
209
+ search = User.search
210
+ search.id_nil = "1"
211
+ search.id_nil.should == true
212
+ end
213
+
214
+ it "should be a Boolean given false" do
215
+ search = User.search
216
+ search.id_nil = false
217
+ search.id_nil.should == false
218
+ end
219
+
220
+ it "should be a Boolean given 'false'" do
221
+ search = User.search
222
+ search.id_nil = "false"
223
+ search.id_nil.should == false
224
+ end
225
+
226
+ it "should be a Boolean given '0'" do
227
+ search = User.search
228
+ search.id_nil = "0"
229
+ search.id_nil.should == false
230
+ end
231
+
232
+ it "should be an Integer given ''" do
233
+ search = User.search
234
+ search.id_gt = ''
235
+ search.id_gt.should == 0
236
+ end
237
+
238
+ it "should be an Integer given 1" do
239
+ search = User.search
240
+ search.id_gt = 1
241
+ search.id_gt.should == 1
242
+ end
243
+
244
+ it "should be an Integer given '1'" do
245
+ search = User.search
246
+ search.id_gt = "1"
247
+ search.id_gt.should == 1
248
+ end
249
+
250
+ it "should be a Float given 1.0" do
251
+ search = Order.search
252
+ search.total_gt = 1.0
253
+ search.total_gt.should == 1.0
254
+ end
255
+
256
+ it "should be a Float given '1'" do
257
+ search = Order.search
258
+ search.total_gt = "1"
259
+ search.total_gt.should == 1.0
260
+ end
261
+
262
+ it "should be a Float given '1.5'" do
263
+ search = Order.search
264
+ search.total_gt = "1.5"
265
+ search.total_gt.should == 1.5
266
+ end
267
+
268
+ it "should be a Range given 1..3" do
269
+ search = Order.search
270
+ search.total_eq = (1..3)
271
+ search.total_eq.should == (1..3)
272
+ end
273
+
274
+ it "should be a Date given 'Jan 1, 2009'" do
275
+ search = Order.search
276
+ search.shipped_on_after = "Jan 1, 2009"
277
+ search.shipped_on_after.should == Date.parse("Jan 1, 2009")
278
+ end
279
+
280
+ it "should be a Time given 'Jan 1, 2009'" do
281
+ search = Order.search
282
+ search.created_at_after = "Jan 1, 2009"
283
+ search.created_at_after.should == Time.zone.parse("Jan 1, 2009")
284
+ end
285
+
286
+ it "should be a Time given 'Jan 1, 2009 9:33AM'" do
287
+ search = Order.search
288
+ search.created_at_after = "Jan 1, 2009 9:33AM"
289
+ search.created_at_after.should == Time.zone.parse("Jan 1, 2009 9:33AM")
290
+ end
291
+
292
+ it "should convert the time to the current zone" do
293
+ search = Order.search
294
+ now = Time.now
295
+ search.created_at_after = now
296
+ search.created_at_after.should == now.in_time_zone
297
+ end
298
+
299
+ it "should be an Array and cast it's values given ['1', '2', '3']" do
300
+ search = Order.search
301
+ search.id_equals_any = ["1", "2", "3"]
302
+ search.id_equals_any.should == [1, 2, 3]
303
+ end
304
+
305
+ it "should type cast association conditions" do
306
+ search = User.search
307
+ search.orders_total_gt = "10"
308
+ search.orders_total_gt.should == 10
309
+ end
310
+
311
+ it "should type cast deep association conditions" do
312
+ search = Company.search
313
+ search.users_orders_total_gt = "10"
314
+ search.users_orders_total_gt.should == 10
315
+ end
316
+ end
317
+ end
318
+
319
+ context "taking action" do
320
+ it "should return all when not given any conditions" do
321
+ 3.times { User.create }
322
+ User.search.all.length.should == 3
323
+ end
324
+
325
+ it "should implement the current scope based on an association" do
326
+ User.create
327
+ company = Company.create
328
+ user = company.users.create
329
+ company.users.search.all.should == [user]
330
+ end
331
+
332
+ it "should implement the current scope based on a named scope" do
333
+ User.named_scope(:four_year_olds, :conditions => {:age => 4})
334
+ (3..5).each { |age| User.create(:age => age) }
335
+ User.four_year_olds.search.all.should == User.find_all_by_age(4)
336
+ end
337
+
338
+ it "should call named scopes for conditions" do
339
+ User.search(:age_less_than => 5).proxy_options.should == User.age_less_than(5).proxy_options
340
+ end
341
+
342
+ it "should alias exact column names to use equals" do
343
+ User.search(:username => "joe").proxy_options.should == User.username_equals("joe").proxy_options
344
+ end
345
+
346
+ it "should recognize conditions with a value of true where the named scope has an arity of 0" do
347
+ User.search(:username_nil => true).proxy_options.should == User.username_nil.proxy_options
348
+ end
349
+
350
+ it "should ignore conditions with a value of false where the named scope has an arity of 0" do
351
+ User.search(:username_nil => false).proxy_options.should == {}
352
+ end
353
+
354
+ it "should not ignore conditions with a value of false where the named scope does not have an arity of 0" do
355
+ User.search(:username_is => false).proxy_options.should == User.username_is(false).proxy_options
356
+ end
357
+
358
+ it "should recognize the order condition" do
359
+ User.search(:order => "ascend_by_username").proxy_options.should == User.ascend_by_username.proxy_options
360
+ end
361
+
362
+ it "should pass array values as multiple arguments with arity -1" do
363
+ User.named_scope(:multiple_args, lambda { |*args|
364
+ raise "This should not be an array, it should be 1" if args.first.is_a?(Array)
365
+ {:conditions => ["id IN (?)", args]}
366
+ })
367
+ User.search(:multiple_args => [1,2]).proxy_options.should == User.multiple_args(1,2).proxy_options
368
+ end
369
+
370
+ it "should pass array as a single value with arity >= 0" do
371
+ User.named_scope(:multiple_args, lambda { |args|
372
+ raise "This should be an array" if !args.is_a?(Array)
373
+ {:conditions => ["id IN (?)", args]}
374
+ })
375
+ User.search(:multiple_args => [1,2]).proxy_options.should == User.multiple_args(1,2).proxy_options
376
+ end
377
+
378
+ it "should not split out dates or times (big fix)" do
379
+ s = User.search
380
+ s.created_at_after = Time.now
381
+ lambda { s.count }.should_not raise_error
382
+ end
383
+
384
+ it "should not include blank values" do
385
+ s = User.search
386
+ s.conditions = {"id_equals" => ""}
387
+ s.proxy_options.should == {}
388
+ end
389
+ end
390
+
391
+ context "method delegation" do
392
+ it "should respond to count" do
393
+ User.create(:username => "bjohnson")
394
+ search1 = User.search(:username => "bjohnson")
395
+ search2 = User.search(:username => "nosnhojb")
396
+ search1.count.should == 1
397
+ search2.count.should == 0
398
+ end
399
+
400
+ it "should respond to empty?" do
401
+ User.create(:username => "bjohnson")
402
+ search1 = User.search(:username => "bjohnson")
403
+ search2 = User.search(:username => "nosnhojb")
404
+ search1.empty?.should == false
405
+ search2.empty?.should == true
406
+ end
407
+
408
+ it "should delegate to named scopes with arity > 1" do
409
+ User.named_scope :paged, lambda {|start, limit| { :limit => limit, :offset => start }}
410
+ User.create(:username => "bjohnson")
411
+ search = User.search(:username => "bjohnson")
412
+ search.paged(0, 1).count.should == 1
413
+ search.paged(0, 0).count.should == 0
414
+ end
415
+ end
416
+ end