From 4384aa017c6502a1ca01a1229e2a7a1b2faad921 Mon Sep 17 00:00:00 2001 From: Dirkjan Bussink Date: Sat, 27 Sep 2008 14:38:03 +0200 Subject: [PATCH] Fix bugs \#444 and \#566 and \#577 which all had the same cause This basically tries to make relationship initalization a bit smarter. The code is pretty ugly, but it just tries loading up relations until they work (that is, all related objects are loaded). This is done for every Model#properties call, but of course cached once they are in a sane state. --- lib/dm-core/associations.rb | 5 +++-- lib/dm-core/model.rb | 15 +++++++++++++++ spec/integration/association_spec.rb | 14 +++++++++++++- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/lib/dm-core/associations.rb b/lib/dm-core/associations.rb index ecc264e8..2d83b130 100644 --- a/lib/dm-core/associations.rb +++ b/lib/dm-core/associations.rb @@ -45,8 +45,8 @@ def many_to_one_relationships end def relationships(repository_name = default_repository_name) - @relationships ||= Hash.new { |h,k| h[k] = k == Repository.default_name ? {} : h[Repository.default_name].dup } - @relationships[repository_name] + @relationships ||= {} + @relationships[repository_name] ||= repository_name == Repository.default_name ? {} : relationships(Repository.default_name).dup end def n @@ -145,6 +145,7 @@ def has(cardinality, name, options = {}) # # @api public def belongs_to(name, options={}) + @_valid_relations = false relationship = ManyToOne.setup(name, self, options) # Please leave this in - I will release contextual serialization soon # which requires this -- guyvdb diff --git a/lib/dm-core/model.rb b/lib/dm-core/model.rb index 9ef7607a..79dab8a4 100644 --- a/lib/dm-core/model.rb +++ b/lib/dm-core/model.rb @@ -154,6 +154,7 @@ def property(name, type, options = {}) create_property_setter(property) properties(repository_name)[property.name] = property + @_valid_relations = false # Add property to the other mappings as well if this is for the default # repository. @@ -195,6 +196,20 @@ def repositories end def properties(repository_name = default_repository_name) + # We need to check whether all relations are already set up. + # If this isn't the case, we try to reload them here + if !@_valid_relations && respond_to?(:many_to_one_relationships) + @_valid_relations = true + begin + many_to_one_relationships.each do |r| + r.child_key + end + rescue NameError + # Apparently not all relations are loaded, + # so we will try again later on + @_valid_relations = false + end + end @properties[repository_name] ||= repository_name == Repository.default_name ? PropertySet.new : properties(Repository.default_name).dup end diff --git a/spec/integration/association_spec.rb b/spec/integration/association_spec.rb index 7c10454c..91c728ba 100644 --- a/spec/integration/association_spec.rb +++ b/spec/integration/association_spec.rb @@ -302,6 +302,18 @@ def self.default_repository_name area.should respond_to(:machine=) end + it 'should create the foreign key property immediately' do + class Duck + include DataMapper::Resource + property :id, Serial + belongs_to :sky + end + Duck.properties.slice(:sky_id).compact.should_not be_empty + duck = Duck.new + duck.should respond_to(:sky_id) + duck.should respond_to(:sky_id=) + end + it 'should load without the parent' it 'should allow substituting the parent' do @@ -331,7 +343,7 @@ class Ostrich end end - FlightlessBirds::Ostrich.properties.slice(:sky_id).should_not be_empty + FlightlessBirds::Ostrich.properties(ADAPTER).slice(:sky_id).compact.should_not be_empty end end