rd_searchlogic 3.0.0.rc

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. data/.gitignore +7 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +308 -0
  4. data/Rakefile +42 -0
  5. data/VERSION.yml +5 -0
  6. data/init.rb +1 -0
  7. data/lib/searchlogic/active_record/association_proxy.rb +19 -0
  8. data/lib/searchlogic/active_record/consistency.rb +49 -0
  9. data/lib/searchlogic/active_record/named_scope_tools.rb +102 -0
  10. data/lib/searchlogic/core_ext/object.rb +43 -0
  11. data/lib/searchlogic/core_ext/proc.rb +17 -0
  12. data/lib/searchlogic/named_scopes/alias_scope.rb +67 -0
  13. data/lib/searchlogic/named_scopes/association_conditions.rb +163 -0
  14. data/lib/searchlogic/named_scopes/association_ordering.rb +44 -0
  15. data/lib/searchlogic/named_scopes/conditions.rb +232 -0
  16. data/lib/searchlogic/named_scopes/or_conditions.rb +141 -0
  17. data/lib/searchlogic/named_scopes/ordering.rb +74 -0
  18. data/lib/searchlogic/rails_helpers.rb +79 -0
  19. data/lib/searchlogic/search.rb +259 -0
  20. data/lib/searchlogic.rb +89 -0
  21. data/rails/init.rb +1 -0
  22. data/spec/searchlogic/active_record/association_proxy_spec.rb +23 -0
  23. data/spec/searchlogic/active_record/consistency_spec.rb +28 -0
  24. data/spec/searchlogic/core_ext/object_spec.rb +9 -0
  25. data/spec/searchlogic/core_ext/proc_spec.rb +8 -0
  26. data/spec/searchlogic/named_scopes/alias_scope_spec.rb +23 -0
  27. data/spec/searchlogic/named_scopes/association_conditions_spec.rb +221 -0
  28. data/spec/searchlogic/named_scopes/association_ordering_spec.rb +29 -0
  29. data/spec/searchlogic/named_scopes/conditions_spec.rb +321 -0
  30. data/spec/searchlogic/named_scopes/or_conditions_spec.rb +66 -0
  31. data/spec/searchlogic/named_scopes/ordering_spec.rb +34 -0
  32. data/spec/searchlogic/search_spec.rb +459 -0
  33. data/spec/spec_helper.rb +146 -0
  34. metadata +123 -0
@@ -0,0 +1,459 @@
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 "condition accessors" do
106
+ # it "should allow setting exact columns individually" do
107
+ # search = User.search
108
+ # search.username = "bjohnson"
109
+ # search.username.should == "bjohnson"
110
+ # end
111
+ #
112
+ # it "should allow setting local column conditions individually" do
113
+ # search = User.search
114
+ # search.username_gt = "bjohnson"
115
+ # search.username_gt.should == "bjohnson"
116
+ # end
117
+ #
118
+ # it "should allow chaining conditions" do
119
+ # user = User.create(:username => "bjohnson", :age => 20)
120
+ # User.create(:username => "bjohnson", :age => 5)
121
+ # search = User.search
122
+ # search.username_equals("bjohnson").age_gt(10)
123
+ # search.all.should == [user]
124
+ # end
125
+ #
126
+ # it "should allow setting association conditions" do
127
+ # search = User.search
128
+ # search.orders_total_gt = 10
129
+ # search.orders_total_gt.should == 10
130
+ # end
131
+ #
132
+ # it "should allow setting pre-existing association conditions" do
133
+ # User.named_scope :uname, lambda { |value| {:conditions => ["users.username = ?", value]} }
134
+ # search = Company.search
135
+ # search.users_uname = "bjohnson"
136
+ # search.users_uname.should == "bjohnson"
137
+ # end
138
+ #
139
+ # it "should allow setting pre-existing association alias conditions" do
140
+ # User.alias_scope :username_has, lambda { |value| User.username_like(value) }
141
+ # search = Company.search
142
+ # search.users_username_has = "bjohnson"
143
+ # search.users_username_has.should == "bjohnson"
144
+ # end
145
+ #
146
+ # it "should allow using custom conditions" do
147
+ # User.named_scope(:four_year_olds, { :conditions => { :age => 4 } })
148
+ # search = User.search
149
+ # search.four_year_olds = true
150
+ # search.four_year_olds.should == true
151
+ # search.proxy_options.should == User.four_year_olds.proxy_options
152
+ # end
153
+ #
154
+ # it "should not merge conflicting conditions into one value" do
155
+ # # This class should JUST be a proxy. It should not do anything more than that.
156
+ # # A user would be allowed to call both named scopes if they wanted.
157
+ # search = User.search
158
+ # search.username_greater_than = "bjohnson1"
159
+ # search.username_gt = "bjohnson2"
160
+ # search.username_greater_than.should == "bjohnson1"
161
+ # search.username_gt.should == "bjohnson2"
162
+ # end
163
+ #
164
+ # it "should allow setting custom conditions individually with an arity of 0" do
165
+ # User.named_scope(:four_year_olds, :conditions => {:age => 4})
166
+ # search = User.search
167
+ # search.four_year_olds = true
168
+ # search.four_year_olds.should == true
169
+ # end
170
+ #
171
+ # it "should allow setting custom conditions individually with an arity of 1" do
172
+ # User.named_scope(:username_should_be, lambda { |u| {:conditions => {:username => u}} })
173
+ # search = User.search
174
+ # search.username_should_be = "bjohnson"
175
+ # search.username_should_be.should == "bjohnson"
176
+ # end
177
+ #
178
+ # it "should not allow setting conditions that are not scopes" do
179
+ # search = User.search
180
+ # lambda { search.unknown = true }.should raise_error(Searchlogic::Search::UnknownConditionError)
181
+ # end
182
+ #
183
+ # it "should not allow setting conditions on sensitive methods" do
184
+ # search = User.search
185
+ # lambda { search.destroy = true }.should raise_error(Searchlogic::Search::UnknownConditionError)
186
+ # end
187
+ #
188
+ # it "should not use the ruby implementation of the id method" do
189
+ # search = User.search
190
+ # search.id.should be_nil
191
+ # end
192
+ #
193
+ # context "type casting" do
194
+ # it "should be a Boolean given true" do
195
+ # search = User.search
196
+ # search.id_nil = true
197
+ # search.id_nil.should == true
198
+ # end
199
+ #
200
+ # it "should be a Boolean given 'true'" do
201
+ # search = User.search
202
+ # search.id_nil = "true"
203
+ # search.id_nil.should == true
204
+ # end
205
+ #
206
+ # it "should be a Boolean given '1'" do
207
+ # search = User.search
208
+ # search.id_nil = "1"
209
+ # search.id_nil.should == true
210
+ # end
211
+ #
212
+ # it "should be a Boolean given false" do
213
+ # search = User.search
214
+ # search.id_nil = false
215
+ # search.id_nil.should == false
216
+ # end
217
+ #
218
+ # it "should be a Boolean given 'false'" do
219
+ # search = User.search
220
+ # search.id_nil = "false"
221
+ # search.id_nil.should == false
222
+ # end
223
+ #
224
+ # it "should be a Boolean given '0'" do
225
+ # search = User.search
226
+ # search.id_nil = "0"
227
+ # search.id_nil.should == false
228
+ # end
229
+ #
230
+ # it "should be an Integer given ''" do
231
+ # search = User.search
232
+ # search.id_gt = ''
233
+ # search.id_gt.should == 0
234
+ # end
235
+ #
236
+ # it "should be an Integer given 1" do
237
+ # search = User.search
238
+ # search.id_gt = 1
239
+ # search.id_gt.should == 1
240
+ # end
241
+ #
242
+ # it "should be an Integer given '1'" do
243
+ # search = User.search
244
+ # search.id_gt = "1"
245
+ # search.id_gt.should == 1
246
+ # end
247
+ #
248
+ # it "should be a Float given 1.0" do
249
+ # search = Order.search
250
+ # search.total_gt = 1.0
251
+ # search.total_gt.should == 1.0
252
+ # end
253
+ #
254
+ # it "should be a Float given '1'" do
255
+ # search = Order.search
256
+ # search.total_gt = "1"
257
+ # search.total_gt.should == 1.0
258
+ # end
259
+ #
260
+ # it "should be a Float given '1.5'" do
261
+ # search = Order.search
262
+ # search.total_gt = "1.5"
263
+ # search.total_gt.should == 1.5
264
+ # end
265
+ #
266
+ # it "should be a Range given 1..3" do
267
+ # search = Order.search
268
+ # search.total_eq = (1..3)
269
+ # search.total_eq.should == (1..3)
270
+ # end
271
+ #
272
+ # it "should be a Date given 'Jan 1, 2009'" do
273
+ # search = Order.search
274
+ # search.shipped_on_after = "Jan 1, 2009"
275
+ # search.shipped_on_after.should == Date.parse("Jan 1, 2009")
276
+ # end
277
+ #
278
+ # it "should be a Time given 'Jan 1, 2009'" do
279
+ # search = Order.search
280
+ # search.created_at_after = "Jan 1, 2009"
281
+ # search.created_at_after.should == Time.zone.parse("Jan 1, 2009")
282
+ # end
283
+ #
284
+ # it "should be a Time given 'Jan 1, 2009 9:33AM'" do
285
+ # search = Order.search
286
+ # search.created_at_after = "Jan 1, 2009 9:33AM"
287
+ # search.created_at_after.should == Time.zone.parse("Jan 1, 2009 9:33AM")
288
+ # end
289
+ #
290
+ # it "should skip time zone conversion for attributes skipped" do
291
+ # search = User.search
292
+ # search.whatever_at_after = "Jan 1, 2009 9:33AM"
293
+ # search.whatever_at_after.should == Time.parse("Jan 1, 2009 9:33AM").utc
294
+ # end
295
+ #
296
+ # it "should convert the time to the current zone" do
297
+ # search = Order.search
298
+ # now = Time.now
299
+ # search.created_at_after = now
300
+ # search.created_at_after.should == now.in_time_zone
301
+ # end
302
+ #
303
+ # it "should be an Array and cast it's values given ['1', '2', '3']" do
304
+ # search = Order.search
305
+ # search.id_equals_any = ["1", "2", "3"]
306
+ # search.id_equals_any.should == [1, 2, 3]
307
+ # end
308
+ #
309
+ # it "should type cast association conditions" do
310
+ # search = User.search
311
+ # search.orders_total_gt = "10"
312
+ # search.orders_total_gt.should == 10
313
+ # end
314
+ #
315
+ # it "should type cast deep association conditions" do
316
+ # search = Company.search
317
+ # search.users_orders_total_gt = "10"
318
+ # search.users_orders_total_gt.should == 10
319
+ # end
320
+ #
321
+ # it "should support Rails' date_select and datetime_select out of the box" do
322
+ # search = Company.search('created_at_after(1i)' => 2000, 'created_at_after(2i)' => 1, 'created_at_after(3i)' => 1)
323
+ # search.created_at_after.should_not be_nil
324
+ # search.created_at_after.should == Time.zone.local(2000, 1, 1)
325
+ # end
326
+ # end
327
+ # end
328
+ #
329
+ # context "#delete" do
330
+ # it "should delete the condition" do
331
+ # search = User.search(:username_like => "bjohnson")
332
+ # search.delete("username_like")
333
+ # search.username_like.should be_nil
334
+ # search.conditions["username_like"].should be_nil
335
+ # end
336
+ # end
337
+ #
338
+ # context "#ordering_by" do
339
+ # it "should return nil if we aren't ordering" do
340
+ # search = User.search
341
+ # search.ordering_by.should be_nil
342
+ # end
343
+ #
344
+ # it "should return the column name for ascending" do
345
+ # search = User.search(:order => "ascend_by_first_name")
346
+ # search.ordering_by.should == "first_name"
347
+ # end
348
+ #
349
+ # it "should return the column name for descending" do
350
+ # search = User.search(:order => "descend_by_first_name")
351
+ # search.ordering_by.should == "first_name"
352
+ # end
353
+ #
354
+ # it "should handle symbols" do
355
+ # search = User.search(:order => :descend_by_first_name)
356
+ # search.ordering_by.should == "first_name"
357
+ # end
358
+ # end
359
+ #
360
+ # context "#method_missing" do
361
+ # context "setting" do
362
+ # it "should call named scopes for conditions" do
363
+ # User.search(:age_less_than => 5).proxy_options.should == User.age_less_than(5).proxy_options
364
+ # end
365
+ #
366
+ # it "should alias exact column names to use equals" do
367
+ # User.search(:username => "joe").proxy_options.should == User.username_equals("joe").proxy_options
368
+ # end
369
+ #
370
+ # it "should recognize conditions with a value of true where the named scope has an arity of 0" do
371
+ # User.search(:username_nil => true).proxy_options.should == User.username_nil.proxy_options
372
+ # end
373
+ #
374
+ # it "should ignore conditions with a value of false where the named scope has an arity of 0" do
375
+ # User.search(:username_nil => false).proxy_options.should == {}
376
+ # end
377
+ #
378
+ # it "should not ignore conditions with a value of false where the named scope does not have an arity of 0" do
379
+ # User.search(:username_is => false).proxy_options.should == User.username_is(false).proxy_options
380
+ # end
381
+ #
382
+ # it "should recognize the order condition" do
383
+ # User.search(:order => "ascend_by_username").proxy_options.should == User.ascend_by_username.proxy_options
384
+ # end
385
+ #
386
+ # it "should pass array values as multiple arguments with arity -1" do
387
+ # User.named_scope(:multiple_args, lambda { |*args|
388
+ # raise "This should not be an array, it should be 1" if args.first.is_a?(Array)
389
+ # {:conditions => ["id IN (?)", args]}
390
+ # })
391
+ # User.search(:multiple_args => [1,2]).proxy_options.should == User.multiple_args(1,2).proxy_options
392
+ # end
393
+ #
394
+ # it "should pass array as a single value with arity >= 0" do
395
+ # User.named_scope(:multiple_args, lambda { |args|
396
+ # raise "This should be an array" if !args.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 not split out dates or times (big fix)" do
403
+ # s = User.search
404
+ # s.created_at_after = Time.now
405
+ # lambda { s.count }.should_not raise_error
406
+ # end
407
+ #
408
+ # it "should not include blank values" do
409
+ # s = User.search
410
+ # s.conditions = {"id_equals" => ""}
411
+ # s.proxy_options.should == {}
412
+ # end
413
+ # end
414
+ # end
415
+ #
416
+ # context "delegation" do
417
+ # it "should return all when not given any conditions" do
418
+ # 3.times { User.create }
419
+ # User.search.all.length.should == 3
420
+ # end
421
+ #
422
+ # it "should implement the current scope based on an association" do
423
+ # User.create
424
+ # company = Company.create
425
+ # user = company.users.create
426
+ # company.users.search.all.should == [user]
427
+ # end
428
+ #
429
+ # it "should implement the current scope based on a named scope" do
430
+ # User.named_scope(:four_year_olds, :conditions => {:age => 4})
431
+ # (3..5).each { |age| User.create(:age => age) }
432
+ # User.four_year_olds.search.all.should == User.find_all_by_age(4)
433
+ # end
434
+ #
435
+ # it "should respond to count" do
436
+ # User.create(:username => "bjohnson")
437
+ # search1 = User.search(:username => "bjohnson")
438
+ # search2 = User.search(:username => "nosnhojb")
439
+ # search1.count.should == 1
440
+ # search2.count.should == 0
441
+ # end
442
+ #
443
+ # it "should respond to empty?" do
444
+ # User.create(:username => "bjohnson")
445
+ # search1 = User.search(:username => "bjohnson")
446
+ # search2 = User.search(:username => "nosnhojb")
447
+ # search1.empty?.should == false
448
+ # search2.empty?.should == true
449
+ # end
450
+ #
451
+ # it "should delegate to named scopes with arity > 1" do
452
+ # User.named_scope :paged, lambda {|start, limit| { :limit => limit, :offset => start }}
453
+ # User.create(:username => "bjohnson")
454
+ # search = User.search(:username => "bjohnson")
455
+ # search.paged(0, 1).count.should == 1
456
+ # search.paged(0, 0).count.should == 0
457
+ # end
458
+ # end
459
+ end
@@ -0,0 +1,146 @@
1
+ require 'spec'
2
+ require 'rubygems'
3
+ require 'ruby-debug'
4
+ require 'active_record'
5
+ require 'active_support/core_ext' if ActiveRecord::VERSION::MAJOR > 2
6
+
7
+ Spec::Matchers.define :eq_scope do |relation2|
8
+ match do |relation1|
9
+ relation1.to_sql.squeeze(' ').downcase == relation2.to_sql.squeeze(' ').downcase
10
+ end
11
+ failure_message_for_should do |relation1|
12
+ "expected\n#{relation2.to_sql.squeeze(' ')}\nto equal\n#{relation1.to_sql.squeeze(' ')}"
13
+ end
14
+ failure_message_for_should_not do |relation1|
15
+ "expected\n#{relation2.to_sql.squeeze(' ')}\nto not equal\n#{relation1.to_sql.squeeze(' ')}"
16
+ end
17
+ end
18
+
19
+ ENV['TZ'] = 'UTC'
20
+ Time.zone = 'Eastern Time (US & Canada)'
21
+
22
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
23
+ ActiveRecord::Base.configurations = true
24
+ ActiveRecord::Base.logger = Logger.new(STDOUT)
25
+
26
+ ActiveRecord::Schema.verbose = false
27
+ ActiveRecord::Schema.define(:version => 1) do
28
+ create_table :audits do |t|
29
+ t.string :auditable_type
30
+ t.integer :auditable_id
31
+ end
32
+
33
+ create_table :companies do |t|
34
+ t.datetime :created_at
35
+ t.datetime :updated_at
36
+ t.string :name
37
+ t.string :description
38
+ t.integer :users_count, :default => 0
39
+ end
40
+
41
+ create_table :user_groups do |t|
42
+ t.string :name
43
+ end
44
+
45
+ create_table :user_groups_users, :id => false do |t|
46
+ t.integer :user_group_id, :null => false
47
+ t.integer :user_id, :null => false
48
+ end
49
+
50
+ create_table :users do |t|
51
+ t.datetime :created_at
52
+ t.datetime :updated_at
53
+ t.integer :company_id
54
+ t.string :username
55
+ t.string :name
56
+ t.integer :age
57
+ t.boolean :male
58
+ t.string :some_type_id
59
+ t.datetime :whatever_at
60
+ end
61
+
62
+ create_table :carts do |t|
63
+ t.datetime :created_at
64
+ t.datetime :updated_at
65
+ t.integer :user_id
66
+ end
67
+
68
+ create_table :orders do |t|
69
+ t.datetime :created_at
70
+ t.datetime :updated_at
71
+ t.integer :user_id
72
+ t.date :shipped_on
73
+ t.float :taxes
74
+ t.float :total
75
+ end
76
+
77
+ create_table :fees do |t|
78
+ t.datetime :created_at
79
+ t.datetime :updated_at
80
+ t.string :owner_type
81
+ t.integer :owner_id
82
+ t.float :cost
83
+ end
84
+
85
+ create_table :line_items do |t|
86
+ t.datetime :created_at
87
+ t.datetime :updated_at
88
+ t.integer :order_id
89
+ t.float :price
90
+ end
91
+ end
92
+
93
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
94
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
95
+ require 'searchlogic'
96
+
97
+ Spec::Runner.configure do |config|
98
+ config.before(:each) do
99
+ class Audit < ActiveRecord::Base
100
+ belongs_to :auditable, :polymorphic => true
101
+ end
102
+
103
+ class Company < ActiveRecord::Base
104
+ has_many :orders, :through => :users
105
+ has_many :users, :dependent => :destroy
106
+ end
107
+
108
+ class UserGroup < ActiveRecord::Base
109
+ has_and_belongs_to_many :users
110
+ end
111
+
112
+ class User < ActiveRecord::Base
113
+ belongs_to :company, :counter_cache => true
114
+ has_many :orders, :dependent => :destroy
115
+ has_many :orders_big, :class_name => 'Order', :conditions => 'total > 100'
116
+ has_and_belongs_to_many :user_groups
117
+
118
+ self.skip_time_zone_conversion_for_attributes = [:whatever_at]
119
+ end
120
+
121
+ class Order < ActiveRecord::Base
122
+ belongs_to :user
123
+ has_many :line_items, :dependent => :destroy
124
+ end
125
+
126
+ class Fee < ActiveRecord::Base
127
+ belongs_to :owner, :polymorphic => true
128
+ end
129
+
130
+ class LineItem < ActiveRecord::Base
131
+ belongs_to :order
132
+ end
133
+
134
+ Company.destroy_all
135
+ User.destroy_all
136
+ Order.destroy_all
137
+ LineItem.destroy_all
138
+ end
139
+
140
+ config.after(:each) do
141
+ Object.send(:remove_const, :Company)
142
+ Object.send(:remove_const, :User)
143
+ Object.send(:remove_const, :Order)
144
+ Object.send(:remove_const, :LineItem)
145
+ end
146
+ end