yoomee-searchlogic 2.4.27

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/.gitignore +6 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +308 -0
  4. data/Rakefile +35 -0
  5. data/VERSION.yml +5 -0
  6. data/init.rb +1 -0
  7. data/lib/searchlogic.rb +56 -0
  8. data/lib/searchlogic/active_record/association_proxy.rb +19 -0
  9. data/lib/searchlogic/active_record/consistency.rb +49 -0
  10. data/lib/searchlogic/active_record/named_scope_tools.rb +101 -0
  11. data/lib/searchlogic/core_ext/object.rb +43 -0
  12. data/lib/searchlogic/core_ext/proc.rb +17 -0
  13. data/lib/searchlogic/named_scopes/alias_scope.rb +67 -0
  14. data/lib/searchlogic/named_scopes/association_conditions.rb +132 -0
  15. data/lib/searchlogic/named_scopes/association_ordering.rb +44 -0
  16. data/lib/searchlogic/named_scopes/conditions.rb +232 -0
  17. data/lib/searchlogic/named_scopes/or_conditions.rb +141 -0
  18. data/lib/searchlogic/named_scopes/ordering.rb +48 -0
  19. data/lib/searchlogic/rails_helpers.rb +79 -0
  20. data/lib/searchlogic/search.rb +26 -0
  21. data/lib/searchlogic/search/base.rb +26 -0
  22. data/lib/searchlogic/search/conditions.rb +58 -0
  23. data/lib/searchlogic/search/date_parts.rb +23 -0
  24. data/lib/searchlogic/search/implementation.rb +14 -0
  25. data/lib/searchlogic/search/method_missing.rb +123 -0
  26. data/lib/searchlogic/search/ordering.rb +10 -0
  27. data/lib/searchlogic/search/scopes.rb +19 -0
  28. data/lib/searchlogic/search/to_yaml.rb +38 -0
  29. data/lib/searchlogic/search/unknown_condition_error.rb +15 -0
  30. data/rails/init.rb +1 -0
  31. data/searchlogic.gemspec +98 -0
  32. data/spec/searchlogic/active_record/association_proxy_spec.rb +23 -0
  33. data/spec/searchlogic/active_record/consistency_spec.rb +28 -0
  34. data/spec/searchlogic/core_ext/object_spec.rb +9 -0
  35. data/spec/searchlogic/core_ext/proc_spec.rb +8 -0
  36. data/spec/searchlogic/named_scopes/alias_scope_spec.rb +23 -0
  37. data/spec/searchlogic/named_scopes/association_conditions_spec.rb +203 -0
  38. data/spec/searchlogic/named_scopes/association_ordering_spec.rb +27 -0
  39. data/spec/searchlogic/named_scopes/conditions_spec.rb +319 -0
  40. data/spec/searchlogic/named_scopes/or_conditions_spec.rb +66 -0
  41. data/spec/searchlogic/named_scopes/ordering_spec.rb +34 -0
  42. data/spec/searchlogic/search_spec.rb +497 -0
  43. data/spec/spec_helper.rb +132 -0
  44. metadata +136 -0
@@ -0,0 +1,66 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
2
+
3
+ describe Searchlogic::NamedScopes::OrConditions 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 Searchlogic::NamedScopes::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,497 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe Searchlogic::Search do
4
+ describe "Implementation" do
5
+ context "#searchlogic" do
6
+ it "should create a search proxy" do
7
+ User.search(:username => "joe").should be_kind_of(Searchlogic::Search)
8
+ end
9
+
10
+ it "should create a search proxy using the same class" do
11
+ User.search.klass.should == User
12
+ end
13
+
14
+ it "should pass on the current scope to the proxy" do
15
+ company = Company.create
16
+ user = company.users.create
17
+ search = company.users.search
18
+ search.current_scope.should == company.users.scope(:find)
19
+ end
20
+ end
21
+ end
22
+
23
+ context "#initialize" do
24
+ it "should require a class" do
25
+ lambda { Searchlogic::Search.new }.should raise_error(ArgumentError)
26
+ end
27
+
28
+ it "should set the conditions" do
29
+ search = User.search(:username => "bjohnson")
30
+ search.conditions.should == {:username => "bjohnson"}
31
+ end
32
+ end
33
+
34
+ context "#clone" do
35
+ it "should clone properly" do
36
+ company = Company.create
37
+ user1 = company.users.create(:age => 5)
38
+ user2 = company.users.create(:age => 25)
39
+ search1 = company.users.search(:age_gt => 10)
40
+ search2 = search1.clone
41
+ search2.age_gt = 1
42
+ search2.all.should == User.all
43
+ search1.all.should == [user2]
44
+ end
45
+
46
+ it "should clone properly without scope" do
47
+ user1 = User.create(:age => 5)
48
+ user2 = User.create(:age => 25)
49
+ search1 = User.search(:age_gt => 10)
50
+ search2 = search1.clone
51
+ search2.age_gt = 1
52
+ search2.all.should == User.all
53
+ search1.all.should == [user2]
54
+ end
55
+ end
56
+
57
+ context "#conditions" do
58
+ it "should set the conditions and be accessible individually" do
59
+ search = User.search
60
+ search.conditions = {:username => "bjohnson"}
61
+ search.username.should == "bjohnson"
62
+ end
63
+
64
+ it "should set the conditions and allow string keys" do
65
+ search = User.search
66
+ search.conditions = {"username" => "bjohnson"}
67
+ search.username.should == "bjohnson"
68
+ end
69
+
70
+ it "should use custom scopes before normalizing" do
71
+ User.create(:username => "bjohnson")
72
+ User.named_scope :username, lambda { |value| {:conditions => {:username => value.reverse}} }
73
+ search1 = User.search(:username => "bjohnson")
74
+ search2 = User.search(:username => "nosnhojb")
75
+ search1.count.should == 0
76
+ search2.count.should == 1
77
+ end
78
+
79
+ # We ignore them upon execution. But we still want to accept the condition so that returning the conditions
80
+ # preserves the values.
81
+ it "should ignore blank values but still return on conditions" do
82
+ search = User.search
83
+ search.conditions = {"username" => ""}
84
+ search.username.should be_nil
85
+ search.conditions.should == {:username => ""}
86
+ end
87
+
88
+ it "should not ignore blank values and should not cast them" do
89
+ search = User.search
90
+ search.conditions = {"id_equals" => ""}
91
+ search.id_equals.should be_nil
92
+ search.conditions.should == {:id_equals => ""}
93
+ end
94
+
95
+ it "should ignore blank values in arrays" do
96
+ search = User.search
97
+ search.conditions = {"username_equals_any" => [""]}
98
+ search.username_equals_any.should be_nil
99
+
100
+ search.conditions = {"id_equals_any" => ["", "1"]}
101
+ search.id_equals_any.should == [1]
102
+ end
103
+ end
104
+
105
+ context "#compact_conditions" do
106
+ it "should remove conditions with blank values" do
107
+ search = User.search
108
+ search.conditions = {"id_equals" => "", "name_equals" => "Ben"}
109
+ search.compact_conditions.should == {:name_equals => "Ben"}
110
+ end
111
+ end
112
+
113
+ context "condition accessors" do
114
+ it "should allow setting exact columns individually" do
115
+ search = User.search
116
+ search.username = "bjohnson"
117
+ search.username.should == "bjohnson"
118
+ end
119
+
120
+ it "should allow setting local column conditions individually" do
121
+ search = User.search
122
+ search.username_gt = "bjohnson"
123
+ search.username_gt.should == "bjohnson"
124
+ end
125
+
126
+ it "should allow chaining conditions" do
127
+ user = User.create(:username => "bjohnson", :age => 20)
128
+ User.create(:username => "bjohnson", :age => 5)
129
+ search = User.search
130
+ search.username_equals("bjohnson").age_gt(10)
131
+ search.all.should == [user]
132
+ end
133
+
134
+ it "should allow setting association conditions" do
135
+ search = User.search
136
+ search.orders_total_gt = 10
137
+ search.orders_total_gt.should == 10
138
+ end
139
+
140
+ it "should allow setting pre-existing association conditions" do
141
+ User.named_scope :uname, lambda { |value| {:conditions => ["users.username = ?", value]} }
142
+ search = Company.search
143
+ search.users_uname = "bjohnson"
144
+ search.users_uname.should == "bjohnson"
145
+ end
146
+
147
+ it "should allow setting pre-existing association alias conditions" do
148
+ User.alias_scope :username_has, lambda { |value| User.username_like(value) }
149
+ search = Company.search
150
+ search.users_username_has = "bjohnson"
151
+ search.users_username_has.should == "bjohnson"
152
+ end
153
+
154
+ it "should allow using custom conditions" do
155
+ User.named_scope(:four_year_olds, { :conditions => { :age => 4 } })
156
+ search = User.search
157
+ search.four_year_olds = true
158
+ search.four_year_olds.should == true
159
+ search.proxy_options.should == User.four_year_olds.proxy_options
160
+ end
161
+
162
+ it "should not merge conflicting conditions into one value" do
163
+ # This class should JUST be a proxy. It should not do anything more than that.
164
+ # A user would be allowed to call both named scopes if they wanted.
165
+ search = User.search
166
+ search.username_greater_than = "bjohnson1"
167
+ search.username_gt = "bjohnson2"
168
+ search.username_greater_than.should == "bjohnson1"
169
+ search.username_gt.should == "bjohnson2"
170
+ end
171
+
172
+ it "should allow setting custom conditions individually with an arity of 0" do
173
+ User.named_scope(:four_year_olds, :conditions => {:age => 4})
174
+ search = User.search
175
+ search.four_year_olds = true
176
+ search.four_year_olds.should == true
177
+ end
178
+
179
+ it "should allow setting custom conditions individually with an arity of 1" do
180
+ User.named_scope(:username_should_be, lambda { |u| {:conditions => {:username => u}} })
181
+ search = User.search
182
+ search.username_should_be = "bjohnson"
183
+ search.username_should_be.should == "bjohnson"
184
+ end
185
+
186
+ it "should not allow setting conditions that are not scopes" do
187
+ search = User.search
188
+ lambda { search.unknown = true }.should raise_error(Searchlogic::Search::UnknownConditionError)
189
+ end
190
+
191
+ it "should not allow setting conditions on sensitive methods" do
192
+ search = User.search
193
+ lambda { search.destroy = true }.should raise_error(Searchlogic::Search::UnknownConditionError)
194
+ end
195
+
196
+ it "should not use the ruby implementation of the id method" do
197
+ search = User.search
198
+ search.id.should be_nil
199
+ end
200
+
201
+ context "type casting" do
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 'true'" do
209
+ search = User.search
210
+ search.id_nil = "true"
211
+ search.id_nil.should == true
212
+ end
213
+
214
+ it "should be a Boolean given '1'" do
215
+ search = User.search
216
+ search.id_nil = "1"
217
+ search.id_nil.should == true
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 'false'" do
227
+ search = User.search
228
+ search.id_nil = "false"
229
+ search.id_nil.should == false
230
+ end
231
+
232
+ it "should be a Boolean given '0'" do
233
+ search = User.search
234
+ search.id_nil = "0"
235
+ search.id_nil.should == false
236
+ end
237
+
238
+ it "should be an Integer given ''" do
239
+ search = User.search
240
+ search.id_gt = ''
241
+ search.id_gt.should == 0
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 an Integer given '1'" do
251
+ search = User.search
252
+ search.id_gt = "1"
253
+ search.id_gt.should == 1
254
+ end
255
+
256
+ it "should be a Float given 1.0" do
257
+ search = Order.search
258
+ search.total_gt = 1.0
259
+ search.total_gt.should == 1.0
260
+ end
261
+
262
+ it "should be a Float given '1'" do
263
+ search = Order.search
264
+ search.total_gt = "1"
265
+ search.total_gt.should == 1.0
266
+ end
267
+
268
+ it "should be a Float given '1.5'" do
269
+ search = Order.search
270
+ search.total_gt = "1.5"
271
+ search.total_gt.should == 1.5
272
+ end
273
+
274
+ it "should be a Range given 1..3" do
275
+ search = Order.search
276
+ search.total_eq = (1..3)
277
+ search.total_eq.should == (1..3)
278
+ end
279
+
280
+ it "should be a Date given 'Jan 1, 2009'" do
281
+ search = Order.search
282
+ search.shipped_on_after = "Jan 1, 2009"
283
+ search.shipped_on_after.should == Date.parse("Jan 1, 2009")
284
+ end
285
+
286
+ it "should be a Time given 'Jan 1, 2009'" do
287
+ search = Order.search
288
+ search.created_at_after = "Jan 1, 2009"
289
+ search.created_at_after.should == Time.zone.parse("Jan 1, 2009")
290
+ end
291
+
292
+ it "should be a Time given 'Jan 1, 2009 9:33AM'" do
293
+ search = Order.search
294
+ search.created_at_after = "Jan 1, 2009 9:33AM"
295
+ search.created_at_after.should == Time.zone.parse("Jan 1, 2009 9:33AM")
296
+ end
297
+
298
+ it "should skip time zone conversion for attributes skipped" do
299
+ search = User.search
300
+ search.whatever_at_after = "Jan 1, 2009 9:33AM"
301
+ search.whatever_at_after.should == Time.parse("Jan 1, 2009 9:33AM").utc
302
+ end
303
+
304
+ it "should convert the time to the current zone" do
305
+ search = Order.search
306
+ now = Time.now
307
+ search.created_at_after = now
308
+ search.created_at_after.should == now.in_time_zone
309
+ end
310
+
311
+ it "should be an Array and cast it's values given ['1', '2', '3']" do
312
+ search = Order.search
313
+ search.id_equals_any = ["1", "2", "3"]
314
+ search.id_equals_any.should == [1, 2, 3]
315
+ end
316
+
317
+ it "should type cast association conditions" do
318
+ search = User.search
319
+ search.orders_total_gt = "10"
320
+ search.orders_total_gt.should == 10
321
+ end
322
+
323
+ it "should type cast deep association conditions" do
324
+ search = Company.search
325
+ search.users_orders_total_gt = "10"
326
+ search.users_orders_total_gt.should == 10
327
+ end
328
+
329
+ it "should support Rails' date_select and datetime_select out of the box" do
330
+ search = Company.search('created_at_after(1i)' => 2000, 'created_at_after(2i)' => 1, 'created_at_after(3i)' => 1)
331
+ search.created_at_after.should_not be_nil
332
+ search.created_at_after.should == Time.zone.local(2000, 1, 1)
333
+ end
334
+ end
335
+ end
336
+
337
+ context "#delete" do
338
+ it "should delete the condition" do
339
+ search = User.search(:username_like => "bjohnson")
340
+ search.delete("username_like")
341
+ search.username_like.should be_nil
342
+ search.conditions["username_like"].should be_nil
343
+ end
344
+ end
345
+
346
+ context "#ordering_by" do
347
+ it "should return nil if we aren't ordering" do
348
+ search = User.search
349
+ search.ordering_by.should be_nil
350
+ end
351
+
352
+ it "should return the column name for ascending" do
353
+ search = User.search(:order => "ascend_by_first_name")
354
+ search.ordering_by.should == "first_name"
355
+ end
356
+
357
+ it "should return the column name for descending" do
358
+ search = User.search(:order => "descend_by_first_name")
359
+ search.ordering_by.should == "first_name"
360
+ end
361
+
362
+ it "should handle symbols" do
363
+ search = User.search(:order => :descend_by_first_name)
364
+ search.ordering_by.should == "first_name"
365
+ end
366
+ end
367
+
368
+ context "#method_missing" do
369
+ context "setting" do
370
+ it "should call named scopes for conditions" do
371
+ User.search(:age_less_than => 5).proxy_options.should == User.age_less_than(5).proxy_options
372
+ end
373
+
374
+ it "should alias exact column names to use equals" do
375
+ User.search(:username => "joe").proxy_options.should == User.username_equals("joe").proxy_options
376
+ end
377
+
378
+ it "should recognize conditions with a value of true where the named scope has an arity of 0" do
379
+ User.search(:username_nil => true).proxy_options.should == User.username_nil.proxy_options
380
+ end
381
+
382
+ it "should ignore conditions with a value of false where the named scope has an arity of 0" do
383
+ User.search(:username_nil => false).proxy_options.should == {}
384
+ end
385
+
386
+ it "should not ignore conditions with a value of false where the named scope does not have an arity of 0" do
387
+ User.search(:username_is => false).proxy_options.should == User.username_is(false).proxy_options
388
+ end
389
+
390
+ it "should recognize the order condition" do
391
+ User.search(:order => "ascend_by_username").proxy_options.should == User.ascend_by_username.proxy_options
392
+ end
393
+
394
+ it "should pass array values as multiple arguments with arity -1" do
395
+ User.named_scope(:multiple_args, lambda { |*args|
396
+ raise "This should not be an array, it should be 1" if args.first.is_a?(Array)
397
+ {:conditions => ["id IN (?)", args]}
398
+ })
399
+ User.search(:multiple_args => [1,2]).proxy_options.should == User.multiple_args(1,2).proxy_options
400
+ end
401
+
402
+ it "should pass array as a single value with arity >= 0" do
403
+ User.named_scope(:multiple_args, lambda { |args|
404
+ raise "This should be an array" if !args.is_a?(Array)
405
+ {:conditions => ["id IN (?)", args]}
406
+ })
407
+ User.search(:multiple_args => [1,2]).proxy_options.should == User.multiple_args([1,2]).proxy_options
408
+ end
409
+
410
+ it "should not split out dates or times (big fix)" do
411
+ s = User.search
412
+ s.created_at_after = Time.now
413
+ lambda { s.count }.should_not raise_error
414
+ end
415
+
416
+ it "should not include blank values" do
417
+ s = User.search
418
+ s.conditions = {"id_equals" => ""}
419
+ s.proxy_options.should == {}
420
+ end
421
+ end
422
+ end
423
+
424
+ context "#respond_to?" do
425
+ it "should respond to created_at_lte" do
426
+ s = User.search
427
+ s.respond_to?(:created_at_lte).should == true
428
+ end
429
+
430
+ it "should respond to created_at" do
431
+ s = User.search
432
+ s.respond_to?(:created_at).should == true
433
+ end
434
+
435
+ it "should not respond to created_at_or_whatever" do
436
+ s = User.search
437
+ s.respond_to?(:created_at_or_whatever)
438
+ end
439
+ end
440
+
441
+ context "delegation" do
442
+ it "should return all when not given any conditions" do
443
+ 3.times { User.create }
444
+ User.search.all.length.should == 3
445
+ end
446
+
447
+ it "should implement the current scope based on an association" do
448
+ User.create
449
+ company = Company.create
450
+ user = company.users.create
451
+ company.users.search.all.should == [user]
452
+ end
453
+
454
+ it "should implement the current scope based on a named scope" do
455
+ User.named_scope(:four_year_olds, :conditions => {:age => 4})
456
+ (3..5).each { |age| User.create(:age => age) }
457
+ User.four_year_olds.search.all.should == User.find_all_by_age(4)
458
+ end
459
+
460
+ it "should respond to count" do
461
+ User.create(:username => "bjohnson")
462
+ search1 = User.search(:username => "bjohnson")
463
+ search2 = User.search(:username => "nosnhojb")
464
+ search1.count.should == 1
465
+ search2.count.should == 0
466
+ end
467
+
468
+ it "should respond to empty?" do
469
+ User.create(:username => "bjohnson")
470
+ search1 = User.search(:username => "bjohnson")
471
+ search2 = User.search(:username => "nosnhojb")
472
+ search1.empty?.should == false
473
+ search2.empty?.should == true
474
+ end
475
+
476
+ it "should delegate to named scopes with arity > 1" do
477
+ User.named_scope :paged, lambda {|start, limit| { :limit => limit, :offset => start }}
478
+ User.create(:username => "bjohnson")
479
+ search = User.search(:username => "bjohnson")
480
+ search.paged(0, 1).count.should == 1
481
+ search.paged(0, 0).count.should == 0
482
+ end
483
+ end
484
+
485
+ context "yaml" do
486
+ it "should load yaml" do
487
+ time = Time.now
488
+ search = User.search(:name_like => "Ben", :created_at_after => time)
489
+ search.current_scope = {:conditions => "1=1"}
490
+ yaml = search.to_yaml
491
+ loaded_search = YAML.load(yaml)
492
+ loaded_search.current_scope.should == {:conditions => "1=1"}
493
+ loaded_search.name_like.should == "Ben"
494
+ loaded_search.created_at_after.should == time
495
+ end
496
+ end
497
+ end