diff --git a/CHANGELOG.md b/CHANGELOG.md index 92fd7a5..d7b824b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## Unreleased +- [378](https://github.com/JsonApiClient/json_api_client/pull/378) - Add the ability to create a subclass of JsonApiClient::Resource to have a modified id method ## 1.21.0 - [#395](https://github.com/JsonApiClient/json_api_client/pull/395) - relaxing faraday dependency to anything less than 2.0 diff --git a/lib/json_api_client/included_data.rb b/lib/json_api_client/included_data.rb index 8cf689c..3018f75 100644 --- a/lib/json_api_client/included_data.rb +++ b/lib/json_api_client/included_data.rb @@ -24,7 +24,7 @@ def initialize(result_set, data) end grouped_included_set.each do |type, resources| - grouped_included_set[type] = resources.index_by(&:id) + grouped_included_set[type] = resources.index_by { |resource| resource.attributes[:id] } end @data = grouped_included_set diff --git a/test/unit/integer_id_test.rb b/test/unit/integer_id_test.rb new file mode 100644 index 0000000..8c8bf04 --- /dev/null +++ b/test/unit/integer_id_test.rb @@ -0,0 +1,183 @@ +# frozen_string_literal: true + +require 'test_helper' + +class BaseResource < JsonApiClient::Resource + self.site = 'http://example.com/' + def id + attributes[:id].to_i if attributes[:id].present? + end +end + +class Actor < BaseResource + has_many :movies +end + +class Movie < BaseResource + belongs_to :actor, shallow_path: true + has_one :director, shallow_path: true +end + +class Director < BaseResource + has_many :movies +end + +NUMERIC_ASSERTION = Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.4') ? Fixnum : Integer + +class IntegerIdTestAssociationTest < MiniTest::Test + + def test_included_document_test_id_from_method_as_integer + stub_request(:get, 'http://example.com/movies/1?include=actor') + .to_return(headers: { content_type: 'application/vnd.api+json', + accept: 'application/vnd.api+json' }, + body: { + data: { + id: '1', + type: 'movie', + attributes: { + actor_id: 1, + director_id: 1, + created_at: '2021-04-20T17:27:06-07:00', + updated_at: '2021-04-20T17:27:07-07:00' + }, + relationships: { + actor: { + data: { + id: '1', + type: 'actor' + } + }, + director: { + data: { + id: '1', + type: 'director' + } + } + } + }, + included: [ + { + id: '1', + type: 'actor', + attributes: { + name: 'Keanu', + updated_at: '2021-04-22T13:50:19-07:00', + created_at: '2021-04-19T16:20:13-07:00' + } + } + ] + }.to_json) + movie = Movie.includes(:actor).find(1).last + assert_equal(NUMERIC_ASSERTION, movie.id.class) + assert_equal(1, movie.id) + assert_equal(String, movie.attributes[:id].class) + assert_equal('1', movie.attributes[:id]) + assert_equal(Actor, movie.actor.class) + assert_equal(NUMERIC_ASSERTION, movie.actor.id.class) + assert_equal(1, movie.actor.id) + assert_equal('1', movie.actor.attributes[:id]) + assert_equal(movie.actor_id, movie.actor.id) + end + + def test_not_included_data_document + stub_request(:get, 'http://example.com/movies/1') + .to_return(headers: { content_type: 'application/vnd.api+json', + accept: 'application/vnd.api+json' }, + body: { + data: { + id: '1', + type: 'movie', + attributes: { + actor_id: 1, + created_at: '2021-04-20T17:27:06-07:00', + updated_at: '2021-04-20T17:27:07-07:00' + }, + relationships: { + actor: { + data: { + id: '1', + type: 'actor' + }, + director: { + data: { + id: '1', + type: 'director' + } + } + } + } + } + }.to_json) + movie = Movie.find(1).last + assert_equal(NUMERIC_ASSERTION, movie.id.class) + assert_equal(1, movie.id) + assert_equal(String, movie.attributes[:id].class) + assert_equal('1', movie.attributes[:id]) + assert_nil(movie.actor) + end + + def test_not_included_data_document_with_relationships_links + stub_request(:get, 'http://example.com/movies/1') + .to_return(headers: { content_type: 'application/vnd.api+json', + accept: 'application/vnd.api+json' }, + body: { + data: { + id: '1', + type: 'movie', + attributes: { + actor_id: 1, + created_at: '2021-04-20T17:27:06-07:00', + updated_at: '2021-04-20T17:27:07-07:00' + }, + relationships: { + actor: { + links: { + self: '/movies/1', + related: '/actors/1' + } + }, + director: { + links: { + self: '/movies/1', + related: '/directors/1' + } + } + } + } + }.to_json) + stub_request(:get, 'http://example.com/directors/1') + .to_return(headers: { content_type: 'application/vnd.api+json', + accept: 'application/vnd.api+json' }, + body: { + data: { + id: '1', + type: 'movie', + attributes: { + actor_id: 1, + created_at: '2021-04-20T17:27:06-07:00', + updated_at: '2021-04-20T17:27:07-07:00' + }, + relationships: { + actor: { + links: { + self: '/movies/1', + related: '/actors/1' + } + }, + director: { + links: { + self: '/movies/1', + related: '/directors/1' + } + } + } + } + }.to_json) + movie = Movie.find(1).last + assert_equal(NUMERIC_ASSERTION, movie.id.class) + assert_equal(1, movie.id) + assert_equal(String, movie.attributes[:id].class) + assert_equal('1', movie.attributes[:id]) + assert_equal(Director, movie.director.class) + end +end