dm-core 0.9.3 → 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/CONTRIBUTING +51 -0
  2. data/FAQ +26 -8
  3. data/Manifest.txt +2 -0
  4. data/Rakefile +2 -1
  5. data/lib/dm-core.rb +8 -3
  6. data/lib/dm-core/adapters/abstract_adapter.rb +2 -2
  7. data/lib/dm-core/adapters/data_objects_adapter.rb +18 -4
  8. data/lib/dm-core/adapters/mysql_adapter.rb +8 -4
  9. data/lib/dm-core/adapters/postgres_adapter.rb +12 -3
  10. data/lib/dm-core/adapters/sqlite3_adapter.rb +1 -1
  11. data/lib/dm-core/associations.rb +1 -0
  12. data/lib/dm-core/associations/many_to_one.rb +7 -1
  13. data/lib/dm-core/associations/one_to_many.rb +1 -1
  14. data/lib/dm-core/associations/relationship.rb +14 -13
  15. data/lib/dm-core/auto_migrations.rb +57 -5
  16. data/lib/dm-core/collection.rb +2 -1
  17. data/lib/dm-core/logger.rb +5 -6
  18. data/lib/dm-core/model.rb +17 -2
  19. data/lib/dm-core/naming_conventions.rb +57 -25
  20. data/lib/dm-core/property.rb +6 -5
  21. data/lib/dm-core/query.rb +20 -16
  22. data/lib/dm-core/resource.rb +24 -7
  23. data/lib/dm-core/version.rb +1 -1
  24. data/script/performance.rb +2 -1
  25. data/script/profile.rb +1 -0
  26. data/spec/integration/association_spec.rb +131 -81
  27. data/spec/integration/association_through_spec.rb +87 -42
  28. data/spec/integration/associations/many_to_many_spec.rb +76 -16
  29. data/spec/integration/associations/many_to_one_spec.rb +6 -1
  30. data/spec/integration/associations/one_to_many_spec.rb +69 -0
  31. data/spec/integration/collection_spec.rb +7 -0
  32. data/spec/integration/query_spec.rb +24 -7
  33. data/spec/integration/resource_spec.rb +59 -10
  34. data/spec/integration/sti_spec.rb +23 -0
  35. data/spec/models/zoo.rb +2 -3
  36. data/spec/spec_helper.rb +9 -1
  37. data/spec/unit/adapters/postgres_adapter_spec.rb +9 -1
  38. data/spec/unit/associations/many_to_one_spec.rb +6 -0
  39. data/spec/unit/auto_migrations_spec.rb +2 -1
  40. data/spec/unit/naming_conventions_spec.rb +26 -18
  41. data/spec/unit/property_spec.rb +3 -4
  42. data/spec/unit/resource_spec.rb +19 -22
  43. data/tasks/gemspec.rb +23 -0
  44. data/tasks/hoe.rb +9 -1
  45. metadata +6 -14
@@ -509,7 +509,8 @@ module DataMapper
509
509
  assert_kind_of 'query', query, Query
510
510
 
511
511
  unless block_given?
512
- raise ArgumentError, 'a block must be supplied for lazy loading results', caller
512
+ # It can be helpful (relationship.rb: 112-13, used for SEL) to have a non-lazy Collection.
513
+ block = lambda {}
513
514
  end
514
515
 
515
516
  @query = query
@@ -4,10 +4,10 @@ require "time" # httpdate
4
4
  # Logger taken from Merb :)
5
5
  #
6
6
  # To replace an existing logger with a new one:
7
- # DataMapper::Logger.set_log(log{String, IO},level{Symbol, String})
7
+ # DataMapper.logger.set_log(log{String, IO},level{Symbol, String})
8
8
  #
9
- # Available logging levels are
10
- # DataMapper::Logger::{ Fatal, Error, Warn, Info, Debug }
9
+ # Available logging levels are:
10
+ # :off, :fatal, :error, :warn, :info, :debug
11
11
  #
12
12
  # Logging via:
13
13
  # DataMapper.logger.fatal(message<String>)
@@ -25,7 +25,7 @@ require "time" # httpdate
25
25
  # ==== Private DataMapper Logger API
26
26
  #
27
27
  # To initialize the logger you create a new object, proxies to set_log.
28
- # DataMapper::Logger.new(log{String, IO},level{Symbol, String})
28
+ # DataMapper::Logger.new(log{String, IO}, level{Symbol, String})
29
29
  #
30
30
  # Logger will not create the file until something is actually logged
31
31
  # This avoids file creation on DataMapper init when it creates the
@@ -147,8 +147,7 @@ module DataMapper
147
147
  end
148
148
 
149
149
  # To replace an existing logger with a new one:
150
- # DataMapper::Logger.set_log(log{String, IO},level{Symbol, String})
151
- #
150
+ # DataMapper.logger.set_log(log{String, IO},level{Symbol, String})
152
151
  #
153
152
  # @param log<IO,String> either an IO object or a name of a logfile.
154
153
  # @param log_level<Symbol> a symbol representing the log level from
data/lib/dm-core/model.rb CHANGED
@@ -31,6 +31,7 @@ module DataMapper
31
31
  def self.extended(model)
32
32
  model.instance_variable_set(:@storage_names, Hash.new { |h,k| h[k] = repository(k).adapter.resource_naming_convention.call(model.send(:default_storage_name)) })
33
33
  model.instance_variable_set(:@properties, Hash.new { |h,k| h[k] = k == Repository.default_name ? PropertySet.new : h[Repository.default_name].dup })
34
+ model.instance_variable_set(:@field_naming_conventions, Hash.new { |h,k| h[k] = repository(k).adapter.field_naming_convention })
34
35
  extra_extensions.each { |extension| model.extend(extension) }
35
36
  end
36
37
 
@@ -39,7 +40,13 @@ module DataMapper
39
40
  target.instance_variable_set(:@properties, Hash.new { |h,k| h[k] = k == Repository.default_name ? PropertySet.new : h[Repository.default_name].dup })
40
41
  target.instance_variable_set(:@base_model, self.base_model)
41
42
  target.instance_variable_set(:@paranoid_properties, @paranoid_properties)
42
- target.instance_variable_set(:@validations, @validations.dup) if self.respond_to?(:validators)
43
+ target.instance_variable_set(:@field_naming_conventions, @field_naming_conventions.dup)
44
+
45
+ if self.respond_to?(:validators)
46
+ @validations.contexts.each do |context, validators|
47
+ validators.each { |validator| target.validators.context(context) << validator }
48
+ end
49
+ end
43
50
 
44
51
  @properties.each do |repository_name,properties|
45
52
  repository(repository_name) do
@@ -120,6 +127,14 @@ module DataMapper
120
127
  @storage_names
121
128
  end
122
129
 
130
+ ##
131
+ # The field naming conventions for this resource across all repositories.
132
+ #
133
+ # @return <Hash(Symbol => String)> All available field naming conventions
134
+ def field_naming_conventions
135
+ @field_naming_conventions
136
+ end
137
+
123
138
  ##
124
139
  # defines a property on the resource
125
140
  #
@@ -262,7 +277,7 @@ module DataMapper
262
277
 
263
278
  ##
264
279
  # This method is deprecated, and will be removed from dm-core.
265
- #
280
+ #
266
281
  def create!(attributes = {})
267
282
  warn("Model#create! is deprecated. It is moving to dm-validations, and will be used to create a record without validations")
268
283
  resource = create(attributes)
@@ -4,7 +4,7 @@ module DataMapper
4
4
  # The default is UnderscoredAndPluralized.
5
5
  # You assign a naming convention like so:
6
6
  #
7
- # repository(:default).adapter.resource_naming_convention = NamingConventions::Underscored
7
+ # repository(:default).adapter.resource_naming_convention = NamingConventions::Resource::Underscored
8
8
  #
9
9
  # You can also easily assign a custom convention with a Proc:
10
10
  #
@@ -21,32 +21,64 @@ module DataMapper
21
21
  # use code like this:
22
22
  #
23
23
  # adapter = DataMapper.setup(:default, "mock://localhost/mock")
24
- # adapter.resource_naming_convention = DataMapper::NamingConventions::Underscored
24
+ # adapter.resource_naming_convention = DataMapper::NamingConventions::Resource::Underscored
25
25
  module NamingConventions
26
26
 
27
- module UnderscoredAndPluralized
28
- def self.call(value)
29
- Extlib::Inflection.pluralize(Extlib::Inflection.underscore(value)).gsub('/','_')
30
- end
31
- end # module UnderscoredAndPluralized
32
-
33
- module UnderscoredAndPluralizedWithoutModule
34
- def self.call(value)
35
- Extlib::Inflection.pluralize(Extlib::Inflection.underscore(Extlib::Inflection.demodulize(value)))
36
- end
37
- end # module UnderscoredAndPluralizedWithoutModule
38
-
39
- module Underscored
40
- def self.call(value)
41
- Extlib::Inflection.underscore(value)
42
- end
43
- end # module Underscored
44
-
45
- module Yaml
46
- def self.call(value)
47
- Extlib::Inflection.pluralize(Extlib::Inflection.underscore(value)) + ".yaml"
48
- end
49
- end # module Yaml
27
+ module Resource
28
+
29
+ module UnderscoredAndPluralized
30
+ def self.call(name)
31
+ Extlib::Inflection.pluralize(Extlib::Inflection.underscore(name)).gsub('/','_')
32
+ end
33
+ end # module UnderscoredAndPluralized
34
+
35
+ module UnderscoredAndPluralizedWithoutModule
36
+ def self.call(name)
37
+ Extlib::Inflection.pluralize(Extlib::Inflection.underscore(Extlib::Inflection.demodulize(name)))
38
+ end
39
+ end # module UnderscoredAndPluralizedWithoutModule
40
+
41
+ module Underscored
42
+ def self.call(name)
43
+ Extlib::Inflection.underscore(name)
44
+ end
45
+ end # module Underscored
46
+
47
+ module Yaml
48
+ def self.call(name)
49
+ Extlib::Inflection.pluralize(Extlib::Inflection.underscore(name)) + ".yaml"
50
+ end
51
+ end # module Yaml
52
+
53
+ end # module Resource
54
+
55
+ module Field
56
+
57
+ module UnderscoredAndPluralized
58
+ def self.call(property)
59
+ Extlib::Inflection.pluralize(Extlib::Inflection.underscore(property.name.to_s)).gsub('/','_')
60
+ end
61
+ end # module UnderscoredAndPluralized
62
+
63
+ module UnderscoredAndPluralizedWithoutModule
64
+ def self.call(property)
65
+ Extlib::Inflection.pluralize(Extlib::Inflection.underscore(Extlib::Inflection.demodulize(property.name.to_s)))
66
+ end
67
+ end # module UnderscoredAndPluralizedWithoutModule
68
+
69
+ module Underscored
70
+ def self.call(property)
71
+ Extlib::Inflection.underscore(property.name.to_s)
72
+ end
73
+ end # module Underscored
74
+
75
+ module Yaml
76
+ def self.call(property)
77
+ Extlib::Inflection.pluralize(Extlib::Inflection.underscore(property.name.to_s)) + ".yaml"
78
+ end
79
+ end # module Yaml
80
+
81
+ end # module Field
50
82
 
51
83
  end # module NamingConventions
52
84
  end # module DataMapper
@@ -279,7 +279,7 @@ module DataMapper
279
279
 
280
280
  attr_reader :primitive, :model, :name, :instance_variable_name,
281
281
  :type, :reader_visibility, :writer_visibility, :getter, :options,
282
- :default, :precision, :scale, :track
282
+ :default, :precision, :scale, :track, :extra_options
283
283
 
284
284
  # Supplies the field in the data-store which the property corresponds to
285
285
  #
@@ -510,8 +510,9 @@ module DataMapper
510
510
  raise ArgumentError, "+type+ was #{type.inspect}, which is not a supported type: #{TYPES * ', '}", caller
511
511
  end
512
512
 
513
- if (unknown_options = options.keys - PROPERTY_OPTIONS).any?
514
- raise ArgumentError, "+options+ contained unknown keys: #{unknown_options * ', '}", caller
513
+ @extra_options = {}
514
+ (options.keys - PROPERTY_OPTIONS).each do |key|
515
+ @extra_options[key] = options.delete(key)
515
516
  end
516
517
 
517
518
  @model = model
@@ -548,7 +549,7 @@ module DataMapper
548
549
  @length = @options.fetch(:length, @options.fetch(:size, DEFAULT_LENGTH))
549
550
  elsif BigDecimal == @primitive || Float == @primitive
550
551
  @precision = @options.fetch(:precision, DEFAULT_PRECISION)
551
-
552
+
552
553
  default_scale = (Float == @primitive) ? DEFAULT_SCALE_FLOAT : DEFAULT_SCALE_BIGDECIMAL
553
554
  @scale = @options.fetch(:scale, default_scale)
554
555
  # @scale = @options.fetch(:scale, DEFAULT_SCALE_BIGDECIMAL)
@@ -575,7 +576,7 @@ module DataMapper
575
576
  end
576
577
 
577
578
  def fields
578
- @fields ||= Hash.new { |h,k| h[k] = repository(k).adapter.field_naming_convention.call(self.name) }
579
+ @fields ||= Hash.new { |h,k| h[k] = self.model.field_naming_conventions[k].call(self) }
579
580
  end
580
581
 
581
582
  def determine_visibility # :nodoc:
data/lib/dm-core/query.rb CHANGED
@@ -47,7 +47,7 @@ module DataMapper
47
47
  # only overwrite the attributes with non-default values
48
48
  @reload = other.reload? unless other.reload? == false
49
49
  @unique = other.unique? unless other.unique? == false
50
- @offset = other.offset unless other.offset == 0
50
+ @offset = other.offset if other.reload? || other.offset != 0
51
51
  @limit = other.limit unless other.limit == nil
52
52
  @order = other.order unless other.order == model.default_order
53
53
  @add_reversed = other.add_reversed? unless other.add_reversed? == false
@@ -189,8 +189,6 @@ module DataMapper
189
189
  @links = normalize_links(@links)
190
190
  @includes = normalize_includes(@includes)
191
191
 
192
- translate_custom_types(@properties, options)
193
-
194
192
  # treat all non-options as conditions
195
193
  (options.keys - OPTIONS - OPTIONS.map { |option| option.to_s }).each do |k|
196
194
  append_condition(k, options[k])
@@ -218,17 +216,6 @@ module DataMapper
218
216
  @conditions = original.conditions.map { |tuple| tuple.dup }
219
217
  end
220
218
 
221
- def translate_custom_types(properties, options)
222
- options.each do |key, value|
223
- case key
224
- when DataMapper::Query::Operator
225
- options[key] = properties[key.target].type.dump(value, properties[key.target]) if properties.has_property?(key.target) && properties[key.target].custom?
226
- when Symbol, String
227
- options[key] = properties[key].type.dump(value, properties[key]) if properties.has_property?(key) && properties[key].custom?
228
- end
229
- end
230
- end
231
-
232
219
  # validate the options
233
220
  def assert_valid_options(options)
234
221
  # validate the reload option and unique option
@@ -440,9 +427,26 @@ module DataMapper
440
427
  raise ArgumentError, "Clause #{clause.inspect} does not map to a DataMapper::Property", caller(2)
441
428
  end
442
429
 
430
+ bind_value = dump_custom_value(property, bind_value)
431
+
443
432
  @conditions << [ operator, property, bind_value ]
444
433
  end
445
434
 
435
+ def dump_custom_value(property_or_path, bind_value)
436
+ case property_or_path
437
+ when DataMapper::Query::Path
438
+ dump_custom_value(property_or_path.property, bind_value)
439
+ when Property
440
+ if property_or_path.custom?
441
+ property_or_path.type.dump(bind_value, property_or_path)
442
+ else
443
+ bind_value
444
+ end
445
+ else
446
+ bind_value
447
+ end
448
+ end
449
+
446
450
  # TODO: check for other mutually exclusive operator + property
447
451
  # combinations. For example if self's conditions were
448
452
  # [ :gt, :amount, 5 ] and the other's condition is [ :lt, :amount, 2 ]
@@ -565,8 +569,8 @@ module DataMapper
565
569
 
566
570
  class Path
567
571
  include Assertions
568
-
569
- %w[ id type ].each { |m| undef_method m }
572
+
573
+ %w[ id type ].each { |m| undef_method m }
570
574
 
571
575
  attr_reader :relationships, :model, :property, :operator
572
576
 
@@ -167,6 +167,17 @@ module DataMapper
167
167
 
168
168
  alias == eql?
169
169
 
170
+ # Computes a hash for the resource
171
+ #
172
+ # ==== Returns
173
+ # <Integer>:: the hash value of the resource
174
+ #
175
+ # -
176
+ # @api public
177
+ def hash
178
+ model.hash + key.hash
179
+ end
180
+
170
181
  # Inspection of the class name and the attributes
171
182
  #
172
183
  # ==== Returns
@@ -233,7 +244,7 @@ module DataMapper
233
244
 
234
245
  def key
235
246
  key_properties.map do |property|
236
- property.get!(self)
247
+ original_values[property.name] || property.get!(self)
237
248
  end
238
249
  end
239
250
 
@@ -259,19 +270,22 @@ module DataMapper
259
270
  # same API through out all of dm-more. dm-validations requires a
260
271
  # context to be passed
261
272
 
262
- child_associations.each { |a| a.save }
273
+ associations_saved = false
274
+ child_associations.each { |a| associations_saved |= a.save }
263
275
 
264
- success = if dirty? || (new_record? && key_properties.any? { |p| p.serial? })
276
+ saved = if dirty? || (new_record? && key_properties.any? { |p| p.serial? })
265
277
  new_record? ? create : update
266
278
  end
267
279
 
268
- if success
280
+ if saved
269
281
  original_values.clear
270
282
  end
271
283
 
272
- parent_associations.each { |a| a.save }
284
+ parent_associations.each { |a| associations_saved |= a.save }
273
285
 
274
- success == true
286
+ # We should return true if the model (or any of its associations)
287
+ # were saved.
288
+ (saved | associations_saved) == true
275
289
  end
276
290
 
277
291
  # destroy the instance, remove it from the repository
@@ -503,7 +517,10 @@ module DataMapper
503
517
  #-
504
518
  # @api public
505
519
  def update_attributes(hash, *update_only)
506
- raise 'Update takes a hash as first parameter' unless hash.is_a?(Hash)
520
+ unless hash.is_a?(Hash)
521
+ raise ArgumentError, "Expecting the first parameter of " +
522
+ "update_attributes to be a hash; got #{hash.inspect}"
523
+ end
507
524
  loop_thru = update_only.empty? ? hash.keys : update_only
508
525
  loop_thru.each { |attr| send("#{attr}=", hash[attr]) }
509
526
  save
@@ -1,3 +1,3 @@
1
1
  module DataMapper
2
- VERSION = '0.9.3' unless defined?(DataMapper::VERSION)
2
+ VERSION = '0.9.4' unless defined?(DataMapper::VERSION)
3
3
  end
@@ -23,6 +23,7 @@ socket_file = Pathname.glob(%w[
23
23
  tmp/mysql.sock
24
24
  /tmp/mysql.sock
25
25
  /var/mysql/mysql.sock
26
+ /var/run/mysqld/mysqld.sock
26
27
  ]).find { |path| path.socket? }
27
28
 
28
29
  configuration_options = {
@@ -130,7 +131,7 @@ puts "Benchmarks will now run #{TIMES} times"
130
131
  RBench.run(TIMES) do
131
132
 
132
133
  column :times
133
- column :dm, :title => "DM 0.9.3"
134
+ column :dm, :title => "DM 0.9.4"
134
135
  column :ar, :title => "AR 2.1"
135
136
  column :diff, :compare => [:dm,:ar]
136
137
 
data/script/profile.rb CHANGED
@@ -18,6 +18,7 @@ SOCKET_FILE = Pathname.glob(%w[
18
18
  /tmp/mysqld.sock
19
19
  /tmp/mysql.sock
20
20
  /var/mysql/mysql.sock
21
+ /var/run/mysqld/mysqld.sock
21
22
  ]).find { |path| path.socket? }
22
23
 
23
24
  DataMapper::Logger.new(DataMapper.root / 'log' / 'dm.log', :debug)
@@ -165,6 +165,19 @@ if ADAPTER
165
165
  belongs_to :parent, :class_name => 'Node', :child_key => [ :parent_id ]
166
166
  end
167
167
 
168
+ class MadeUpThing
169
+ include DataMapper::Resource
170
+
171
+ def self.default_repository_name
172
+ ADAPTER
173
+ end
174
+
175
+ property :id, Serial
176
+ property :name, String
177
+ belongs_to :area
178
+ belongs_to :machine
179
+ end
180
+
168
181
  module Models
169
182
  class Project
170
183
  include DataMapper::Resource
@@ -227,6 +240,7 @@ if ADAPTER
227
240
 
228
241
  belongs_to :galaxy
229
242
  end
243
+
230
244
  end
231
245
 
232
246
  describe DataMapper::Associations do
@@ -274,6 +288,7 @@ if ADAPTER
274
288
  before do
275
289
  Machine.auto_migrate!(ADAPTER)
276
290
  Area.auto_migrate!(ADAPTER)
291
+ MadeUpThing.auto_migrate!(ADAPTER)
277
292
 
278
293
  machine1 = Machine.create(:name => 'machine1')
279
294
  machine2 = Machine.create(:name => 'machine2')
@@ -299,10 +314,9 @@ if ADAPTER
299
314
  end
300
315
 
301
316
  it 'should save both the object and parent if both are new' do
302
- pending "This is fixed"
303
317
  area1 = Area.new(:name => 'area1')
304
318
  area1.machine = Machine.new(:name => 'machine1')
305
- area1.machine.save
319
+ area1.save
306
320
  area1.machine_id.should == area1.machine.id
307
321
  end
308
322
 
@@ -338,6 +352,16 @@ if ADAPTER
338
352
  Area.new(:machine => machine).machine_id.should == machine.id
339
353
  end
340
354
 
355
+ it "should be able to set an association obtained from another association" do
356
+ machine1 = Machine.first(:name => 'machine1')
357
+ area1 = Area.first(:name => 'area1')
358
+ area1.machine = machine1
359
+
360
+ m = MadeUpThing.create(:machine => area1.machine, :name => "Weird")
361
+
362
+ m.machine_id.should == machine1.id
363
+ end
364
+
341
365
  it 'should save the parent upon saving of child' do
342
366
  e = Machine.new(:name => 'machine10')
343
367
  y = Area.create(:name => 'area10', :machine => e)
@@ -346,6 +370,13 @@ if ADAPTER
346
370
  Machine.first(:name => 'machine10').should_not be_nil
347
371
  end
348
372
 
373
+ it 'should set and retrieve associations on not yet saved objects' do
374
+ e = Machine.create(:name => 'machine10')
375
+ y = e.areas.build(:name => 'area10')
376
+
377
+ y.machine.name.should == 'machine10'
378
+ end
379
+
349
380
  it 'should convert NULL parent ids into nils' do
350
381
  Area.first(:name => 'area2').machine.should be_nil
351
382
  end
@@ -379,6 +410,17 @@ if ADAPTER
379
410
 
380
411
  lambda { y.reload }.should_not raise_error
381
412
  end
413
+
414
+ it "should have machine when created using machine_id" do
415
+ m = Machine.create(:name => 'machineX')
416
+ a = Area.new(:machine_id => m.id)
417
+ a.machine.should == m
418
+ end
419
+
420
+ it "should not have a machine when orphaned" do
421
+ a = Area.new(:machine_id => 42)
422
+ a.machine.should be_nil
423
+ end
382
424
  end
383
425
 
384
426
  describe 'one to one associations' do
@@ -697,7 +739,7 @@ if ADAPTER
697
739
  end
698
740
  property :id, Serial
699
741
  property :name, String
700
- belongs_to :shop, :class_name => 'Sweets::Shop'
742
+ belongs_to :shop
701
743
  has 1, :wife
702
744
  has n, :children
703
745
  has n, :toys, :through => :children
@@ -1178,18 +1220,19 @@ if ADAPTER
1178
1220
  @li = LeftItem.new(:name => "li#{number}")
1179
1221
  end
1180
1222
 
1181
- it "should add to the assocaiton from the left" do
1182
- pending "Waiting on Many To Many to be implemented"
1183
- create_item_pair "0000"
1184
- @ri.save; @li.save
1185
- @ri.should_not be_new_record
1186
- @li.should_not be_new_record
1223
+ it "should add to the association from the left" do
1224
+ pending "Waiting on Many To Many to be implemented" do
1225
+ create_item_pair "0000"
1226
+ @ri.save; @li.save
1227
+ @ri.should_not be_new_record
1228
+ @li.should_not be_new_record
1187
1229
 
1188
- @li.right_items << @ri
1189
- @li.right_items.should include(@ri)
1190
- @li.reload
1191
- @ri.reload
1192
- @li.right_items.should include(@ri)
1230
+ @li.right_items << @ri
1231
+ @li.right_items.should include(@ri)
1232
+ @li.reload
1233
+ @ri.reload
1234
+ @li.right_items.should include(@ri)
1235
+ end
1193
1236
  end
1194
1237
 
1195
1238
  it "should add to the association from the right" do
@@ -1205,93 +1248,100 @@ if ADAPTER
1205
1248
  @ri.left_items.should include(@li)
1206
1249
  end
1207
1250
 
1208
- it "should load the assocaited collection from the either side" do
1209
- pending "Waiting on Many To Many to be implemented"
1210
- create_item_pair "0020"
1211
- @ri.save; @li.save
1212
- @ri.left_items << @li
1213
- @ri.reload; @li.reload
1251
+ it "should load the associated collection from the either side" do
1252
+ pending "Waiting on Many To Many to be implemented" do
1253
+ create_item_pair "0020"
1254
+ @ri.save; @li.save
1255
+ @ri.left_items << @li
1256
+ @ri.reload; @li.reload
1214
1257
 
1215
- @ri.left_items.should include(@li)
1216
- @li.right_items.should include(@ri)
1258
+ @ri.left_items.should include(@li)
1259
+ @li.right_items.should include(@ri)
1260
+ end
1217
1261
  end
1218
1262
 
1219
- it "should load the assocatied collection from the right" do
1220
- pending "Waiting on Many To Many to be implemented"
1221
- create_item_pair "0030"
1222
- @ri.save; @li.save
1223
- @li.right_items << @li
1224
- @ri.reload; @li.reload
1225
-
1226
- @ri.left_items.should include(@li)
1227
- @li.right_items.should include(@ri)
1263
+ it "should load the associated collection from the right" do
1264
+ pending "Waiting on Many To Many to be implemented" do
1265
+ create_item_pair "0030"
1266
+ @ri.save; @li.save
1267
+ @li.right_items << @li
1268
+ @ri.reload; @li.reload
1228
1269
 
1270
+ @ri.left_items.should include(@li)
1271
+ @li.right_items.should include(@ri)
1272
+ end
1229
1273
  end
1230
1274
 
1231
1275
  it "should save the left side of the association if new record" do
1232
- pending "Waiting on Many To Many to be implemented"
1233
- create_item_pair "0040"
1234
- @ri.save
1235
- @li.should be_new_record
1236
- @ri.left_items << @li
1237
- @li.should_not be_new_record
1276
+ pending "Waiting on Many To Many to be implemented" do
1277
+ create_item_pair "0040"
1278
+ @ri.save
1279
+ @li.should be_new_record
1280
+ @ri.left_items << @li
1281
+ @li.should_not be_new_record
1282
+ end
1238
1283
  end
1239
1284
 
1240
- it "should save the right side of the assocaition if new record" do
1241
- pending "Waiting on Many To Many to be implemented"
1242
- create_item_pair "0050"
1243
- @li.save
1244
- @ri.should be_new_record
1245
- @li.right_items << @ri
1246
- @ri.should_not be_new_record
1285
+ it "should save the right side of the association if new record" do
1286
+ pending "Waiting on Many To Many to be implemented" do
1287
+ create_item_pair "0050"
1288
+ @li.save
1289
+ @ri.should be_new_record
1290
+ @li.right_items << @ri
1291
+ @ri.should_not be_new_record
1292
+ end
1247
1293
  end
1248
1294
 
1249
- it "should save both side of the assocaition if new record" do
1250
- pending "Waiting on Many To Many to be implemented"
1251
- create_item_pair "0060"
1252
- @li.should be_new_record
1253
- @ri.should be_new_record
1254
- @ri.left_items << @li
1255
- @ri.should_not be_new_record
1256
- @li.should_not be_new_record
1295
+ it "should save both side of the association if new record" do
1296
+ pending "Waiting on Many To Many to be implemented" do
1297
+ create_item_pair "0060"
1298
+ @li.should be_new_record
1299
+ @ri.should be_new_record
1300
+ @ri.left_items << @li
1301
+ @ri.should_not be_new_record
1302
+ @li.should_not be_new_record
1303
+ end
1257
1304
  end
1258
1305
 
1259
1306
  it "should remove an item from the left collection without destroying the item" do
1260
- pending "Waiting on Many To Many to be implemented"
1261
- create_item_pair "0070"
1262
- @li.save; @ri.save
1263
- @ri.left_items << @li
1264
- @ri.reload; @li.reload
1265
- @ri.left_items.should include(@li)
1266
- @ri.left_items.delete(@li)
1267
- @ri.left_items.should_not include(@li)
1268
- @li.reload
1269
- LeftItem.get(@li.id).should_not be_nil
1307
+ pending "Waiting on Many To Many to be implemented" do
1308
+ create_item_pair "0070"
1309
+ @li.save; @ri.save
1310
+ @ri.left_items << @li
1311
+ @ri.reload; @li.reload
1312
+ @ri.left_items.should include(@li)
1313
+ @ri.left_items.delete(@li)
1314
+ @ri.left_items.should_not include(@li)
1315
+ @li.reload
1316
+ LeftItem.get(@li.id).should_not be_nil
1317
+ end
1270
1318
  end
1271
1319
 
1272
1320
  it "should remove an item from the right collection without destroying the item" do
1273
- pending "Waiting on Many To Many to be implemented"
1274
- create_item_pair "0080"
1275
- @li.save; @ri.save
1276
- @li.right_items << @ri
1277
- @li.reload; @ri.reload
1278
- @li.right_items.should include(@ri)
1279
- @li.right_items.delete(@ri)
1280
- @li.right_items.should_not include(@ri)
1281
- @ri.reload
1282
- RightItem.get(@ri.id).should_not be_nil
1321
+ pending "Waiting on Many To Many to be implemented" do
1322
+ create_item_pair "0080"
1323
+ @li.save; @ri.save
1324
+ @li.right_items << @ri
1325
+ @li.reload; @ri.reload
1326
+ @li.right_items.should include(@ri)
1327
+ @li.right_items.delete(@ri)
1328
+ @li.right_items.should_not include(@ri)
1329
+ @ri.reload
1330
+ RightItem.get(@ri.id).should_not be_nil
1331
+ end
1283
1332
  end
1284
1333
 
1285
1334
  it "should remove the item from the collection when an item is deleted" do
1286
- pending "Waiting on Many To Many to be implemented"
1287
- create_item_pair "0090"
1288
- @li.save; @ri.save
1289
- @ri.left_items << @li
1290
- @ri.reload; @li.reload
1291
- @ri.left_items.should include(@li)
1292
- @li.destroy
1293
- @ri.reload
1294
- @ri.left_items.should_not include(@li)
1335
+ pending "Waiting on Many To Many to be implemented" do
1336
+ create_item_pair "0090"
1337
+ @li.save; @ri.save
1338
+ @ri.left_items << @li
1339
+ @ri.reload; @li.reload
1340
+ @ri.left_items.should include(@li)
1341
+ @li.destroy
1342
+ @ri.reload
1343
+ @ri.left_items.should_not include(@li)
1344
+ end
1295
1345
  end
1296
1346
  end
1297
1347
  end