From: Tom Hughes Date: Sat, 21 Jun 2008 17:38:17 +0000 (+0000) Subject: Use a polymorphic association to model relation members and add X-Git-Tag: live~8332 X-Git-Url: https://git.openstreetmap.org./rails.git/commitdiff_plain/b527d27674f0ad4ad66075def914bde695d4d88e Use a polymorphic association to model relation members and add associations for upward links from objects to relations that they are a part of. --- diff --git a/app/models/node.rb b/app/models/node.rb index cc646b768..4393f2526 100644 --- a/app/models/node.rb +++ b/app/models/node.rb @@ -10,11 +10,16 @@ class Node < GeoRecord validates_numericality_of :latitude, :longitude validate :validate_position - has_many :ways, :through => :way_nodes + belongs_to :user + has_many :old_nodes, :foreign_key => :id + has_many :way_nodes - belongs_to :user - + has_many :ways, :through => :way_nodes + + has_many :containing_relation_members, :as => :member + has_many :containing_relations, :through => :containing_relation_members + # Sanity check the latitude and longitude and add an error if it's broken def validate_position errors.add_to_base("Node is not in the world") unless in_world? diff --git a/app/models/relation.rb b/app/models/relation.rb index cedfaf656..cd2d67cdd 100644 --- a/app/models/relation.rb +++ b/app/models/relation.rb @@ -1,14 +1,17 @@ class Relation < ActiveRecord::Base require 'xml/libxml' + set_table_name 'current_relations' + belongs_to :user + has_many :old_relations, :foreign_key => 'id', :order => 'version' + has_many :relation_members, :foreign_key => 'id' has_many :relation_tags, :foreign_key => 'id' - has_many :old_relations, :foreign_key => 'id', :order => 'version' - - set_table_name 'current_relations' + has_many :containing_relation_members, :as => :member + has_many :containing_relations, :through => :containing_relation_members def self.from_xml(xml, create=false) begin diff --git a/app/models/relation_member.rb b/app/models/relation_member.rb index 79102853e..9ff4f46f3 100644 --- a/app/models/relation_member.rb +++ b/app/models/relation_member.rb @@ -1,30 +1,23 @@ class RelationMember < ActiveRecord::Base set_table_name 'current_relation_members' - - # problem with RelationMember is that it may link to any one - # object (a node, a way, another relation), and belongs_to is - # not flexible enough for that. So we do this, which is ugly, - # but fortunately rails won't actually run the SQL behind that - # unless someone really accesses .node, .way, or - # .relation - which is what we do below based on member_type. - # (and no: the :condition on belongs_to doesn't work here as - # it is a condition on the *referenced* object not the - # *referencing* object!) - belongs_to :node, :foreign_key => "member_id" - belongs_to :way, :foreign_key => "member_id" - belongs_to :relation, :foreign_key => "member_id" + belongs_to :member, :polymorphic => true, :foreign_type => :member_class + belongs_to :relation, :foreign_key => :id + + def after_find + self[:member_class] = self.member_type.capitalize + end - # so we define this "member" function that returns whatever it - # is. - - def member() - return (member_type == "node") ? node : (member_type == "way") ? way : relation + def after_initialize + self[:member_class] = self.member_type.capitalize end - # NOTE - relations are SUBJECTS of memberships. The fact that nodes, - # ways, and relations can be the OBJECT of a membership, - # i.e. a node/way/relation can be referenced throgh a - # RelationMember object, is NOT modelled in rails, i.e. these links - # have to be resolved manually, on demand. + def before_save + self.member_type = self[:member_class].downcase + end + + def member_type=(type) + self[:member_type] = type + self[:member_class] = type.capitalize + end end diff --git a/app/models/way.rb b/app/models/way.rb index f1dc76eb4..8ae6b4084 100644 --- a/app/models/way.rb +++ b/app/models/way.rb @@ -1,15 +1,19 @@ class Way < ActiveRecord::Base require 'xml/libxml' + set_table_name 'current_ways' + belongs_to :user - has_many :nodes, :through => :way_nodes, :order => 'sequence_id' + has_many :old_ways, :foreign_key => 'id', :order => 'version' + has_many :way_nodes, :foreign_key => 'id', :order => 'sequence_id' - has_many :way_tags, :foreign_key => 'id' + has_many :nodes, :through => :way_nodes, :order => 'sequence_id' - has_many :old_ways, :foreign_key => 'id', :order => 'version' + has_many :way_tags, :foreign_key => 'id' - set_table_name 'current_ways' + has_many :containing_relation_members, :class_name => "RelationMember", :as => :member + has_many :containing_relations, :class_name => "Relation", :through => :containing_relation_members, :source => :relation def self.from_xml(xml, create=false) begin