From: Andy Allan Date: Fri, 18 Aug 2017 09:08:54 +0000 (+0100) Subject: Refactor the from_xml methods to act on existing trace objects. X-Git-Tag: live~3900^2~1 X-Git-Url: https://git.openstreetmap.org./rails.git/commitdiff_plain/c647aa3d4db16ec7fcef6822609c7ef85a17ee5a Refactor the from_xml methods to act on existing trace objects. Setting the new tags with the = operator takes care of removing the old ones, and is the same approach as taken by the tagstring= method. Fixes #1600 --- diff --git a/app/controllers/trace_controller.rb b/app/controllers/trace_controller.rb index eaeb4f5d0..4e10a6c0c 100644 --- a/app/controllers/trace_controller.rb +++ b/app/controllers/trace_controller.rb @@ -263,15 +263,7 @@ class TraceController < ApplicationController trace = Trace.visible.find(params[:id]) if trace.user == current_user - new_trace = Trace.from_xml(request.raw_post) - - unless new_trace && new_trace.id == trace.id - raise OSM::APIBadUserInput.new("The id in the url (#{trace.id}) is not the same as provided in the xml (#{new_trace.id})") - end - - trace.description = new_trace.description - trace.tags = new_trace.tags - trace.visibility = new_trace.visibility + trace.from_xml(request.raw_post) trace.save! head :ok diff --git a/app/models/trace.rb b/app/models/trace.rb index eed09dbe5..b7b96c65e 100644 --- a/app/models/trace.rb +++ b/app/models/trace.rb @@ -172,13 +172,12 @@ class Trace < ActiveRecord::Base el1 end - # Read in xml as text and return it's Node object representation - def self.from_xml(xml, create = false) + def from_xml(xml, create = false) p = XML::Parser.string(xml, :options => XML::Parser::Options::NOERROR) doc = p.parse doc.find("//osm/gpx_file").each do |pt| - return Trace.from_xml_node(pt, create) + return from_xml_node(pt, create) end raise OSM::APIBadXMLError.new("trace", xml, "XML doesn't contain an osm/gpx_file element.") @@ -186,34 +185,31 @@ class Trace < ActiveRecord::Base raise OSM::APIBadXMLError.new("trace", xml, ex.message) end - def self.from_xml_node(pt, create = false) - trace = Trace.new - + def from_xml_node(pt, create = false) raise OSM::APIBadXMLError.new("trace", pt, "visibility missing") if pt["visibility"].nil? - trace.visibility = pt["visibility"] + self.visibility = pt["visibility"] unless create raise OSM::APIBadXMLError.new("trace", pt, "ID is required when updating.") if pt["id"].nil? - trace.id = pt["id"].to_i + id = pt["id"].to_i # .to_i will return 0 if there is no number that can be parsed. # We want to make sure that there is no id with zero anyway - raise OSM::APIBadUserInput.new("ID of trace cannot be zero when updating.") if trace.id.zero? + raise OSM::APIBadUserInput.new("ID of trace cannot be zero when updating.") if id.zero? + raise OSM::APIBadUserInput.new("The id in the url (#{self.id}) is not the same as provided in the xml (#{id})") unless self.id == id end # We don't care about the time, as it is explicitly set on create/update/delete # We don't care about the visibility as it is implicit based on the action # and set manually before the actual delete - trace.visible = true + self.visible = true description = pt.find("description").first raise OSM::APIBadXMLError.new("trace", pt, "description missing") if description.nil? - trace.description = description.content + self.description = description.content - pt.find("tag").each do |tag| - trace.tags.build(:tag => tag.content) + self.tags = pt.find("tag").collect do |tag| + Tracetag.new(:tag => tag.content) end - - trace end def xml_file diff --git a/test/controllers/trace_controller_test.rb b/test/controllers/trace_controller_test.rb index b635f3e57..a23b59473 100644 --- a/test/controllers/trace_controller_test.rb +++ b/test/controllers/trace_controller_test.rb @@ -942,7 +942,10 @@ class TraceControllerTest < ActionController::TestCase assert_response :success updated = Trace.find(trace.id) - assert_equal trace.tags, updated.tags + # Ensure there's only one tag in the database after updating + assert_equal Tracetag.count, 1 + # The new tag object might have a different id, so check the string representation + assert_equal trace.tagstring, updated.tagstring end # Check deleting a trace through the api