X-Git-Url: https://git.openstreetmap.org./rails.git/blobdiff_plain/0638eefe22586b9e9f20448e99bfe9a37f3b1540..e583ead8f8da3d730e1edf8f14db0d3cb0fb7eac:/app/models/way.rb?ds=sidebyside diff --git a/app/models/way.rb b/app/models/way.rb index a87244563..09d1dafa0 100644 --- a/app/models/way.rb +++ b/app/models/way.rb @@ -3,63 +3,96 @@ class Way < ActiveRecord::Base belongs_to :user - has_many :way_segments, :foreign_key => 'id' + has_many :way_segments, :foreign_key => 'id', :order => 'sequence_id' has_many :way_tags, :foreign_key => 'id' + has_many :old_ways, :foreign_key => 'id', :order => 'version' + set_table_name 'current_ways' def self.from_xml(xml, create=false) - p = XML::Parser.new - p.string = xml - doc = p.parse + begin + p = XML::Parser.new + p.string = xml + doc = p.parse - way = Way.new + way = Way.new - doc.find('//osm/way').each do |pt| - if !create and pt['id'] != '0' - way.id = pt['id'].to_i - end + doc.find('//osm/way').each do |pt| + if !create and pt['id'] != '0' + way.id = pt['id'].to_i + end - if create - way.timestamp = Time.now - way.visible = true - else - if pt['timestamp'] - way.timestamp = Time.parse(pt['timestamp']) + if create + way.timestamp = Time.now + way.visible = true + else + if pt['timestamp'] + way.timestamp = Time.parse(pt['timestamp']) + end end - end - pt.find('tag').each do |tag| - way.add_tag_keyval(tag['k'], tag['v']) - end + pt.find('tag').each do |tag| + way.add_tag_keyval(tag['k'], tag['v']) + end - pt.find('seg').each do |seg| - way.add_seg_num(seg['id']) + pt.find('seg').each do |seg| + way.add_seg_num(seg['id']) + end end - + rescue + way = nil end return way end def to_xml - doc = XML::Document.new - doc.encoding = 'UTF-8' - root = XML::Node.new 'osm' - root['version'] = '0.4' - root['generator'] = 'OpenStreetMap server' + doc = OSM::API.new.get_xml_doc + doc.root << to_xml_node() + return doc + end - doc.root = root - + def to_xml_node(visible_segments = nil, user_display_name_cache = nil) el1 = XML::Node.new 'way' el1['id'] = self.id.to_s el1['visible'] = self.visible.to_s el1['timestamp'] = self.timestamp.xmlschema + + user_display_name_cache = {} if user_display_name_cache.nil? - self.way_segments.each do |seg| # FIXME need to make sure they come back in the right order - e = XML::Node.new 'seg' - e['id'] = seg.segment_id.to_s - el1 << e + if user_display_name_cache and user_display_name_cache.key?(self.user_id) + # use the cache if available + elsif self.user.data_public? + user_display_name_cache[self.user_id] = self.user.display_name + else + user_display_name_cache[self.user_id] = nil + end + + el1['user'] = user_display_name_cache[self.user_id] unless user_display_name_cache[self.user_id].nil? + + # make sure segments are output in sequence_id order + ordered_segments = [] + self.way_segments.each do |seg| + if visible_segments + # if there is a list of visible segments then use that to weed out deleted segments + if visible_segments[seg.segment_id] + ordered_segments[seg.sequence_id] = seg.segment_id.to_s + end + else + # otherwise, manually go to the db to check things + if seg.segment.visible? and seg.segment.from_node.visible? and seg.segment.to_node.visible? + ordered_segments[seg.sequence_id] = seg.segment_id.to_s + end + end + end + + ordered_segments.each do |seg_id| + if seg_id and seg_id != '0' + e = XML::Node.new 'seg' + e['id'] = seg_id + el1 << e + end end self.way_tags.each do |tag| @@ -68,21 +101,37 @@ class Way < ActiveRecord::Base e['v'] = tag.v el1 << e end - - root << el1 - return doc - end + return el1 + end def segs - @segs = Array.new unless @segs + unless @segs + @segs = Array.new + self.way_segments.each do |seg| + @segs += [seg.segment_id] + end + end @segs end def tags - @tags = Hash.new unless @tags + unless @tags + @tags = Hash.new + self.way_tags.each do |tag| + @tags[tag.k] = tag.v + end + end @tags end + def segs=(s) + @segs = s + end + + def tags=(t) + @tags = t + end + def add_seg_num(n) @segs = Array.new unless @segs @segs << n.to_i @@ -94,35 +143,58 @@ class Way < ActiveRecord::Base end def save_with_history - t = Time.now - self.timestamp = t - self.save - - WayTag.delete_all(['id = ?', self.id]) - - self.tags.each do |k,v| - tag = WayTag.new - tag.k = k - tag.v = v - tag.id = self.id - tag.save + begin + Way.transaction do + t = Time.now + self.timestamp = t + self.save! + + tags = self.tags + + WayTag.delete_all(['id = ?', self.id]) + + tags.each do |k,v| + tag = WayTag.new + tag.k = k + tag.v = v + tag.id = self.id + tag.save! + end + + segs = self.segs + + WaySegment.delete_all(['id = ?', self.id]) + + i = 1 + segs.each do |n| + seg = WaySegment.new + seg.id = self.id + seg.segment_id = n + seg.sequence_id = i + seg.save! + i += 1 + end + + old_way = OldWay.from_way(self) + old_way.timestamp = t + old_way.save_with_dependencies! + end + + return true + rescue + return nil end + end - WaySegment.delete_all(['id = ?', self.id]) - - i = 0 + def preconditions_ok? + return false if self.segs.empty? self.segs.each do |n| - seg = WaySegment.new - seg.id = self.id - seg.segment_id = n - seg.sequence_id = i - seg.save - i += 1 + segment = Segment.find(:first, :conditions => ["id = ?", n]) + unless segment and segment.visible and segment.preconditions_ok? + return false + end end - - old_way = OldWay.from_way(self) - old_way.timestamp = t - old_way.save_with_dependencies + return true end end