From 7ae0af3949cf76b6f7c858eff3311d35526f128b Mon Sep 17 00:00:00 2001 From: "J.W. Koelewijn" Date: Thu, 26 Jan 2012 12:24:11 +0100 Subject: [PATCH] Updated relationship initialization to be able to support more complex resource model creation in which the behaviour is mixed in from several modules, specs are added to display the wrong behaviour --- lib/dm-core/model.rb | 16 ++++--- lib/dm-core/model/property.rb | 10 +++-- lib/dm-core/model/relationship.rb | 8 +++- spec/public/model/relationship_spec.rb | 61 ++++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 10 deletions(-) diff --git a/lib/dm-core/model.rb b/lib/dm-core/model.rb index d4e377e70..3e7a8e787 100644 --- a/lib/dm-core/model.rb +++ b/lib/dm-core/model.rb @@ -209,11 +209,12 @@ def self.extra_extensions def self.extended(descendant) descendants << descendant - descendant.instance_variable_set(:@valid, false) - descendant.instance_variable_set(:@base_model, descendant) - descendant.instance_variable_set(:@storage_names, {}) - descendant.instance_variable_set(:@default_order, {}) - + descendant.instance_eval do + @valid = false unless instance_variable_defined?(:@valid) + @base_model ||= descendant + @storage_names ||= {} + @default_order ||= {} + end descendant.extend(Chainable) extra_extensions.each { |mod| descendant.extend(mod) } @@ -224,6 +225,11 @@ def self.extended(descendant) def inherited(descendant) descendants << descendant + descendant.instance_eval do + @valid = false unless instance_variable_defined?(:@valid) + @base_model ||= base_model + end + descendant.instance_variable_set(:@valid, false) descendant.instance_variable_set(:@base_model, base_model) descendant.instance_variable_set(:@storage_names, @storage_names.dup) diff --git a/lib/dm-core/model/property.rb b/lib/dm-core/model/property.rb index 09fa15aee..fcc692675 100644 --- a/lib/dm-core/model/property.rb +++ b/lib/dm-core/model/property.rb @@ -7,13 +7,17 @@ module Property Model.append_extensions self, DataMapper::Property::Lookup def self.extended(model) - model.instance_variable_set(:@properties, {}) - model.instance_variable_set(:@field_naming_conventions, {}) + model.instance_eval do + @properties = {} + @field_naming_conventions ||= {} + end end def inherited(model) - model.instance_variable_set(:@properties, {}) + model.instance_eval do + @properties ||= {} + end model.instance_variable_set(:@field_naming_conventions, @field_naming_conventions.dup) @properties.each do |repository_name, properties| diff --git a/lib/dm-core/model/relationship.rb b/lib/dm-core/model/relationship.rb index aeb5380ae..ec1c2cd15 100644 --- a/lib/dm-core/model/relationship.rb +++ b/lib/dm-core/model/relationship.rb @@ -17,7 +17,9 @@ module Relationship # # @api private def self.extended(model) - model.instance_variable_set(:@relationships, {}) + model.instance_eval do + @relationships ||= {} + end end # When DataMapper model is inherited, relationships @@ -25,7 +27,9 @@ def self.extended(model) # # @api private def inherited(model) - model.instance_variable_set(:@relationships, {}) + model.instance_eval do + @relationships ||= {} + end @relationships.each do |repository_name, relationships| model_relationships = model.relationships(repository_name) diff --git a/spec/public/model/relationship_spec.rb b/spec/public/model/relationship_spec.rb index 2cacfc57b..ae5eaaf2c 100644 --- a/spec/public/model/relationship_spec.rb +++ b/spec/public/model/relationship_spec.rb @@ -1038,3 +1038,64 @@ class ::Company end end end + +describe DataMapper::Associations do + before :all do + module ::Vehicle + def self.included(base) + base.extend(ClassMethods) + end + + module ClassMethods + + def vehicle_with_wheels(*args) + include DataMapper::Resource + + property :id, DataMapper::Property::Serial + property :license_plate, String + end + end + end + + class Exhaust + include DataMapper::Resource + + property :id, Serial + belongs_to :car + end + + class Suspension + include DataMapper::Resource + + property :id, Serial + property :brand, String + end + + class Car + include DataMapper::Resource + has n, :suspensions + end + + class Car + include DataMapper::Resource + include Vehicle + + vehicle_with_wheels + + property :number_of_seats, Integer + has n, :exhausts + + end + + DataMapper.finalize + end + + it "should have all relationships when Resource is included once" do + Exhaust.relationships.any? {|r| r.name == :car }.should be_true + end + + it "should not forget about relationships when Resource is included more than once" do + Car.relationships.any? {|r| r.name == :exhausts }.should be_true + Car.relationships.any? {|r| r.name == :suspensions }.should be_true + end +end