From: Tom Hughes Date: Wed, 30 Aug 2017 20:09:32 +0000 (+0100) Subject: Merge remote-tracking branch 'upstream/pull/1614' X-Git-Tag: live~4404 X-Git-Url: https://git.openstreetmap.org/rails.git/commitdiff_plain/f1faffd4d1954f855f6450fc8e5c62ea5f457113?hp=33845759acf79dc9a0c8460e6363d767bcd86847 Merge remote-tracking branch 'upstream/pull/1614' --- diff --git a/app/controllers/trace_controller.rb b/app/controllers/trace_controller.rb index eaeb4f5d0..41c488e0f 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.update_from_xml(request.raw_post) trace.save! head :ok diff --git a/app/models/trace.rb b/app/models/trace.rb index eed09dbe5..160060a6d 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 update_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 update_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 update_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 4610852fb..a23b59473 100644 --- a/test/controllers/trace_controller_test.rb +++ b/test/controllers/trace_controller_test.rb @@ -931,6 +931,23 @@ class TraceControllerTest < ActionController::TestCase assert_equal nt.visibility, t.visibility end + # Test that updating a trace doesn't duplicate the tags + def test_api_update_tags + tracetag = create(:tracetag) + trace = tracetag.trace + basic_authorization trace.user.display_name, "test" + + content trace.to_xml + put :api_update, :params => { :id => trace.id } + assert_response :success + + updated = Trace.find(trace.id) + # 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 def test_api_delete public_trace_file = create(:trace, :visibility => "public")