From e76d0bb0b15478da9db956a5f7e52ae13d721a05 Mon Sep 17 00:00:00 2001 From: Forest Date: Thu, 7 Sep 2017 12:17:10 -0700 Subject: [PATCH] Saving should not remove a story's labels. (Fixes #110) (#112) --- lib/tracker_api/resources/story.rb | 18 ++++++++++++++++-- test/story_test.rb | 4 ---- test/vcr/cassettes/create_story_comment.json | 2 +- test/vcr/cassettes/get_story_in_epic.json | 2 +- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/lib/tracker_api/resources/story.rb b/lib/tracker_api/resources/story.rb index 0cb6cbe..3e1ebad 100644 --- a/lib/tracker_api/resources/story.rb +++ b/lib/tracker_api/resources/story.rb @@ -21,7 +21,7 @@ class Story attribute :integration_id, Integer attribute :kind, String attribute :label_ids, [Integer] - attribute :labels, [Label], default: nil + attribute :labels, [Label] attribute :name, String attribute :owned_by_id, Integer # deprecated! attribute :owned_by, Person @@ -54,7 +54,20 @@ class UpdateRepresenter < Representable::Decorator property :deadline property :requested_by_id property :owner_ids, if: ->(_) { !owner_ids.blank? } - collection :labels, class: Label, decorator: Label::UpdateRepresenter, render_empty: true + + # Use render_empty: false to address: https://github.com/dashofcode/tracker_api/issues/110 + # - The default value of the labels attribute in Resources::Story is an empty array. + # - If the value of labels is not change (i.e. not dirty) then when a new Story + # is created from the dirty attributes in the save method the labels attributes becomes + # an empty array again. render_empty: false keeps this from rendering in the json passed + # in the API PUT request. It is is empty then the labels will be cleared. + # - The next issue is that there is no way to delete all the labels from a Story with + # the current implementation. + # + # NOTE: There are two solutions: 1) remove dirty tracking 2) rewrite without virtus + # SEE: https://github.com/dashofcode/tracker_api/pull/98 + collection :labels, class: Label, decorator: Label::UpdateRepresenter, render_empty: false + property :integration_id property :external_id end @@ -170,6 +183,7 @@ def create_comment(params) # Save changes to an existing Story. def save raise ArgumentError, 'Can not update a story with an unknown project_id.' if project_id.nil? + return self unless dirty? Endpoints::Story.new(client).update(self, UpdateRepresenter.new(Story.new(self.dirty_attributes))) end diff --git a/test/story_test.rb b/test/story_test.rb index 08992e9..b1f180e 100644 --- a/test/story_test.rb +++ b/test/story_test.rb @@ -79,10 +79,6 @@ original_labels = story_in_epic.labels original_label_list = story_in_epic.label_list - VCR.use_cassette('create story comment', record: :new_episodes) do - story_in_epic.create_comment text: "This is a test comment." - end - story_in_epic.estimate = 2 story_in_epic.current_state = 'started' diff --git a/test/vcr/cassettes/create_story_comment.json b/test/vcr/cassettes/create_story_comment.json index 13d4dfc..fbff5f4 100644 --- a/test/vcr/cassettes/create_story_comment.json +++ b/test/vcr/cassettes/create_story_comment.json @@ -1 +1 @@ -{"http_interactions":[{"request":{"method":"post","uri":"https://www.pivotaltracker.com/services/v5/projects/1027488/stories/66728030/comments","body":{"encoding":"UTF-8","string":"{\"text\":\"This is a test comment.\"}"},"headers":{"User-Agent":["Ruby/2.3.1 (x86_64-darwin15; ruby) TrackerApi/1.7.0 Faraday/0.9.2"],"X-TrackerToken":["d55c3bc1f74346b843ca84ba340b29bf"],"Content-Type":["application/json"]}},"response":{"status":{"code":200,"message":null},"headers":{"Access-Control-Allow-Credentials":["false"],"Access-Control-Allow-Headers":["X-TrackerToken,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-Tracker-Warn-Unless-Project-Version-Is"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Origin":["*"],"Cache-Control":["max-age=0, private, must-revalidate"],"Content-Type":["application/json; charset=utf-8"],"Date":["Wed, 03 May 2017 23:29:45 GMT"],"Etag":["\"0ae883818e80288c11e26305f2b9d9de\""],"Server":["nginx + Phusion Passenger"],"Status":["200 OK"],"Strict-Transport-Security":["max-age=31536000; includeSubDomains; preload"],"X-Content-Type-Options":["nosniff"],"X-Powered-By":["Phusion Passenger Enterprise"],"X-Rack-Cache":["invalidate, pass"],"X-Request-Id":["3f4a528c8ca42da1af2a0949c3012633"],"X-Runtime":["0.154335"],"X-Tracker-Client-Pinger-Interval":["20"],"X-Tracker-Project-Version":["238"],"X-Ua-Compatible":["IE=Edge,chrome=1"],"X-Vcap-Request-Id":["7cabdec2-5557-489c-46e5-bf1fc55621ac"],"X-Xss-Protection":["1; mode=block"],"Content-Length":["178"],"Connection":["keep-alive"]},"body":{"encoding":"ASCII-8BIT","string":"{\"kind\":\"comment\",\"id\":170363251,\"story_id\":66728030,\"text\":\"This is a test comment.\",\"person_id\":1266314,\"created_at\":\"2017-05-03T23:29:45Z\",\"updated_at\":\"2017-05-03T23:29:45Z\"}"},"http_version":null},"recorded_at":"Wed, 03 May 2017 23:29:45 GMT"}],"recorded_with":"VCR 2.9.3"} \ No newline at end of file +{"http_interactions":[{"request":{"method":"post","uri":"https://www.pivotaltracker.com/services/v5/projects/1027488/stories/66728030/comments","body":{"encoding":"UTF-8","string":"{\"text\":\"This is a test comment.\"}"},"headers":{"User-Agent":["Ruby/2.3.1 (x86_64-darwin15; ruby) TrackerApi/1.7.1 Faraday/0.9.2"],"X-TrackerToken":["d55c3bc1f74346b843ca84ba340b29bf"],"Content-Type":["application/json"]}},"response":{"status":{"code":200,"message":null},"headers":{"Access-Control-Allow-Credentials":["false"],"Access-Control-Allow-Headers":["X-TrackerToken,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-Tracker-Warn-Unless-Project-Version-Is"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Origin":["*"],"Cache-Control":["max-age=0, private, must-revalidate"],"Content-Type":["application/json; charset=utf-8"],"Date":["Wed, 09 Aug 2017 22:02:51 GMT"],"Etag":["\"dda3e3dc085f4c98ff5f20fa92abf0ee\""],"Server":["nginx + Phusion Passenger"],"Status":["200 OK"],"Strict-Transport-Security":["max-age=31536000; includeSubDomains; preload"],"X-Content-Type-Options":["nosniff"],"X-Powered-By":["Phusion Passenger Enterprise"],"X-Rack-Cache":["invalidate, pass"],"X-Request-Id":["c5ee798d0eaea73fe5df666bf14ca615"],"X-Runtime":["0.286458"],"X-Tracker-Client-Pinger-Interval":["20"],"X-Tracker-Project-Version":["294"],"X-Ua-Compatible":["IE=Edge,chrome=1"],"X-Vcap-Request-Id":["ffae63d3-492f-49db-4eb4-81f7ba85633b"],"X-Xss-Protection":["1; mode=block"],"Content-Length":["178"],"Via":["1.1 google"],"Alt-Svc":["clear"]},"body":{"encoding":"ASCII-8BIT","string":"{\"kind\":\"comment\",\"id\":178211829,\"story_id\":66728030,\"text\":\"This is a test comment.\",\"person_id\":1266314,\"created_at\":\"2017-08-09T22:02:51Z\",\"updated_at\":\"2017-08-09T22:02:51Z\"}"},"http_version":null},"recorded_at":"Wed, 09 Aug 2017 22:02:57 GMT"}],"recorded_with":"VCR 2.9.3"} \ No newline at end of file diff --git a/test/vcr/cassettes/get_story_in_epic.json b/test/vcr/cassettes/get_story_in_epic.json index aa3292f..474f216 100644 --- a/test/vcr/cassettes/get_story_in_epic.json +++ b/test/vcr/cassettes/get_story_in_epic.json @@ -1 +1 @@ -{"http_interactions":[{"request":{"method":"get","uri":"https://www.pivotaltracker.com/services/v5/projects/1027488/stories/66728030","body":{"encoding":"US-ASCII","string":""},"headers":{"User-Agent":["Ruby/2.3.1 (x86_64-darwin15; ruby) TrackerApi/1.7.0 Faraday/0.9.2"],"X-TrackerToken":["d55c3bc1f74346b843ca84ba340b29bf"]}},"response":{"status":{"code":200,"message":null},"headers":{"Access-Control-Allow-Credentials":["false"],"Access-Control-Allow-Headers":["X-TrackerToken,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-Tracker-Warn-Unless-Project-Version-Is"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Origin":["*"],"Cache-Control":["max-age=0, private, must-revalidate"],"Content-Type":["application/json; charset=utf-8"],"Date":["Wed, 03 May 2017 23:29:45 GMT"],"Etag":["\"1fd905e46c27c4c82fef34c22783bf3e\""],"Server":["nginx + Phusion Passenger"],"Status":["200 OK"],"Strict-Transport-Security":["max-age=31536000; includeSubDomains; preload"],"X-Content-Type-Options":["nosniff"],"X-Powered-By":["Phusion Passenger Enterprise"],"X-Rack-Cache":["miss"],"X-Request-Id":["6ff827dfb4fc2bbf7eb887e83b285aec"],"X-Runtime":["0.035813"],"X-Tracker-Client-Pinger-Interval":["20"],"X-Tracker-Project-Version":["237"],"X-Ua-Compatible":["IE=Edge,chrome=1"],"X-Vcap-Request-Id":["e5b6fb6b-cf70-4614-5d67-0824b5d23cce"],"X-Xss-Protection":["1; mode=block"],"Content-Length":["650"],"Connection":["keep-alive"]},"body":{"encoding":"ASCII-8BIT","string":"{\"kind\":\"story\",\"id\":66728030,\"created_at\":\"2014-02-17T00:00:00Z\",\"updated_at\":\"2017-05-03T23:23:55Z\",\"estimate\":2,\"story_type\":\"feature\",\"name\":\"Admin can review all order questions and send responses to shoppers\",\"current_state\":\"started\",\"requested_by_id\":1266314,\"url\":\"https://www.pivotaltracker.com/story/show/66728030\",\"project_id\":1027488,\"owner_ids\":[],\"labels\":[{\"id\":7849080,\"project_id\":1027488,\"kind\":\"label\",\"name\":\"admin\",\"created_at\":\"2014-03-02T07:11:04Z\",\"updated_at\":\"2014-03-02T07:11:04Z\"},{\"id\":7849094,\"project_id\":1027488,\"kind\":\"label\",\"name\":\"orders\",\"created_at\":\"2014-03-02T07:11:05Z\",\"updated_at\":\"2014-03-02T07:11:05Z\"}]}"},"http_version":null},"recorded_at":"Wed, 03 May 2017 23:29:45 GMT"}],"recorded_with":"VCR 2.9.3"} \ No newline at end of file +{"http_interactions":[{"request":{"method":"get","uri":"https://www.pivotaltracker.com/services/v5/projects/1027488/stories/66728030","body":{"encoding":"US-ASCII","string":""},"headers":{"User-Agent":["Ruby/2.3.1 (x86_64-darwin15; ruby) TrackerApi/1.7.1 Faraday/0.9.2"],"X-TrackerToken":["d55c3bc1f74346b843ca84ba340b29bf"]}},"response":{"status":{"code":200,"message":null},"headers":{"Access-Control-Allow-Credentials":["false"],"Access-Control-Allow-Headers":["X-TrackerToken,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-Tracker-Warn-Unless-Project-Version-Is"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Origin":["*"],"Cache-Control":["max-age=0, private, must-revalidate"],"Content-Type":["application/json; charset=utf-8"],"Date":["Thu, 10 Aug 2017 00:43:48 GMT"],"Etag":["\"ad00e2519a528a75040db99754645a00\""],"Server":["nginx + Phusion Passenger"],"Status":["200 OK"],"Strict-Transport-Security":["max-age=31536000; includeSubDomains; preload"],"X-Content-Type-Options":["nosniff"],"X-Powered-By":["Phusion Passenger Enterprise"],"X-Rack-Cache":["miss"],"X-Request-Id":["9cf32ccf6c3d7c7a9ef006f20ade805b"],"X-Runtime":["0.038823"],"X-Tracker-Client-Pinger-Interval":["20"],"X-Tracker-Project-Version":["307"],"X-Ua-Compatible":["IE=Edge,chrome=1"],"X-Vcap-Request-Id":["7fee37f6-76fe-4ec5-4b1b-9f05ff3d471f"],"X-Xss-Protection":["1; mode=block"],"Content-Length":["650"],"Via":["1.1 google"],"Alt-Svc":["clear"]},"body":{"encoding":"ASCII-8BIT","string":"{\"kind\":\"story\",\"id\":66728030,\"created_at\":\"2014-02-17T00:00:00Z\",\"updated_at\":\"2017-08-09T23:58:18Z\",\"estimate\":3,\"story_type\":\"feature\",\"name\":\"Admin can review all order questions and send responses to shoppers\",\"current_state\":\"started\",\"requested_by_id\":1266314,\"url\":\"https://www.pivotaltracker.com/story/show/66728030\",\"project_id\":1027488,\"owner_ids\":[],\"labels\":[{\"id\":7849080,\"project_id\":1027488,\"kind\":\"label\",\"name\":\"admin\",\"created_at\":\"2014-03-02T07:11:04Z\",\"updated_at\":\"2014-03-02T07:11:04Z\"},{\"id\":7849094,\"project_id\":1027488,\"kind\":\"label\",\"name\":\"orders\",\"created_at\":\"2014-03-02T07:11:05Z\",\"updated_at\":\"2014-03-02T07:11:05Z\"}]}"},"http_version":null},"recorded_at":"Thu, 10 Aug 2017 00:43:54 GMT"}],"recorded_with":"VCR 2.9.3"} \ No newline at end of file