From 43b023604ed9df1b0ec17f98578d0e4e054b520e Mon Sep 17 00:00:00 2001 From: Denis Talakevich Date: Tue, 19 Mar 2019 10:47:37 +0200 Subject: [PATCH 1/3] add failing test that reproduces issue #334 --- test/unit/creation_test.rb | 46 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/test/unit/creation_test.rb b/test/unit/creation_test.rb index a793a926..68bbeb61 100644 --- a/test/unit/creation_test.rb +++ b/test/unit/creation_test.rb @@ -18,6 +18,16 @@ def after_create_method class Author < TestResource end + class User < TestResource + has_one :skill_level + + properties :first_name, type: :string + end + + class SkillLevel < TestResource + property :title, type: :string + end + def stub_simple_creation stub_request(:post, "http://example.com/articles") .with(headers: {content_type: "application/vnd.api+json", accept: "application/vnd.api+json"}, body: { @@ -341,4 +351,40 @@ def test_create_with_custom_type assert_equal '1', file.id end + def test_access_loaded_relationship_instance + stub_request(:get, 'http://example.com/skill_levels/1') + .to_return(headers: {content_type: 'application/vnd.api+json'}, body: { + data: { + type: 'skill_levels', + id: '1', + attributes: { + title: 'newbie' + } + } + }.to_json) + + stub_request(:get, 'http://example.com/skill_levels/2') + .to_return(headers: {content_type: 'application/vnd.api+json'}, body: { + data: { + type: 'skill_levels', + id: '1', + attributes: { + title: 'pro' + } + } + }.to_json) + + skill_level = SkillLevel.find(1).first + user = User.new(first_name: 'Joe', relationships: { skill_level: skill_level }) + + assert_equal ({'data'=>{'type'=>'skill_levels', 'id'=>'1'}}), user.relationships.skill_level + assert_kind_of SkillLevel, user.skill_level + assert_equal '1', user.skill_level.id + # test that object is cached and not recreated each time + assert_equal user.skill_level.object_id, user.skill_level.object_id + + user.relationships.skill_level = SkillLevel.find(2).first + assert_equal '2', user.skill_level.id + end + end From 361178010c6592a0c2d6a2e9c77e261bb174db9a Mon Sep 17 00:00:00 2001 From: Denis Talakevich Date: Mon, 25 Mar 2019 15:12:26 +0200 Subject: [PATCH 2/3] retrieve assigned relationship record via association getter method with caching --- .../associations/base_association.rb | 7 +++++++ lib/json_api_client/associations/has_one.rb | 7 ++++++- lib/json_api_client/resource.rb | 13 ++++++++++++- test/unit/creation_test.rb | 4 ++-- 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/lib/json_api_client/associations/base_association.rb b/lib/json_api_client/associations/base_association.rb index dfc8166e..6894b353 100644 --- a/lib/json_api_client/associations/base_association.rb +++ b/lib/json_api_client/associations/base_association.rb @@ -21,6 +21,13 @@ def data(url) def from_result_set(result_set) result_set.to_a end + + def load_records(data) + data.map do |d| + record_class = Utils.compute_type(klass, d["type"].classify) + record_class.load id: d["id"] + end + end end end end diff --git a/lib/json_api_client/associations/has_one.rb b/lib/json_api_client/associations/has_one.rb index 4d1418a2..fd29872e 100644 --- a/lib/json_api_client/associations/has_one.rb +++ b/lib/json_api_client/associations/has_one.rb @@ -5,7 +5,12 @@ class Association < BaseAssociation def from_result_set(result_set) result_set.first end + + def load_records(data) + record_class = Utils.compute_type(klass, data["type"].classify) + record_class.load id: data["id"] + end end end end -end \ No newline at end of file +end diff --git a/lib/json_api_client/resource.rb b/lib/json_api_client/resource.rb index 68505520..9dbcde95 100644 --- a/lib/json_api_client/resource.rb +++ b/lib/json_api_client/resource.rb @@ -537,7 +537,11 @@ def included_data_for(name, relationship_definition) def relationship_data_for(name, relationship_definition) # look in included data if relationship_definition.key?("data") - return included_data_for(name, relationship_definition) + if relationships.attribute_changed?(name) + return relation_objects_for(name, relationship_definition) + else + return included_data_for(name, relationship_definition) + end end url = relationship_definition["links"]["related"] @@ -548,6 +552,13 @@ def relationship_data_for(name, relationship_definition) nil end + def relation_objects_for(name, relationship_definition) + data = relationship_definition["data"] + assoc = association_for(name) + return if data.nil? || assoc.nil? + assoc.load_records(data) + end + def method_missing(method, *args) relationship_definition = relationship_definition_for(method) diff --git a/test/unit/creation_test.rb b/test/unit/creation_test.rb index 68bbeb61..9798b902 100644 --- a/test/unit/creation_test.rb +++ b/test/unit/creation_test.rb @@ -367,7 +367,7 @@ def test_access_loaded_relationship_instance .to_return(headers: {content_type: 'application/vnd.api+json'}, body: { data: { type: 'skill_levels', - id: '1', + id: '2', attributes: { title: 'pro' } @@ -383,7 +383,7 @@ def test_access_loaded_relationship_instance # test that object is cached and not recreated each time assert_equal user.skill_level.object_id, user.skill_level.object_id - user.relationships.skill_level = SkillLevel.find(2).first + user.skill_level = SkillLevel.find(2).first assert_equal '2', user.skill_level.id end From 18997e59d22a5a79e8f56a560fbc6681a17be2ae Mon Sep 17 00:00:00 2001 From: Denis Talakevich Date: Tue, 26 Mar 2019 09:34:36 +0200 Subject: [PATCH 3/3] fix byebug version fo travis ci --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 163acf72..0b5a6e5c 100644 --- a/Gemfile +++ b/Gemfile @@ -11,5 +11,5 @@ gem 'addressable', '~> 2.2' gem "codeclimate-test-reporter", group: :test, require: nil group :development, :test do - gem 'byebug', platforms: [:mri_20, :mri_21, :mri_22] + gem 'byebug', '~> 10.0', platforms: [:mri_20, :mri_21, :mri_22] end