diff --git a/lib/active_model/serializer/adapter/json_api.rb b/lib/active_model/serializer/adapter/json_api.rb index 974e4c63a..6e0dd29c2 100644 --- a/lib/active_model/serializer/adapter/json_api.rb +++ b/lib/active_model/serializer/adapter/json_api.rb @@ -61,6 +61,16 @@ def resource_identifier_type_for(serializer) end end + def resource_identifier_type_for_belongs_to(parent_object, association_key) + type = parent_object.class.reflections[association_key].class_name + if ActiveModel::Serializer.config.jsonapi_resource_type == :singular + type = type.singularize + else + type = type.pluralize + end + type.underscore + end + def resource_identifier_id_for(serializer) if serializer.respond_to?(:id) serializer.id @@ -69,6 +79,10 @@ def resource_identifier_id_for(serializer) end end + def resource_identifier_id_for_belongs_to(parent_object, association_key) + parent_object.send("#{association_key}_id") + end + def resource_identifier_for(serializer) type = resource_identifier_type_for(serializer) id = resource_identifier_id_for(serializer) @@ -76,6 +90,17 @@ def resource_identifier_for(serializer) { id: id.to_s, type: type } end + def resource_identifier_for_belongs_to(parent_object, association_key) + type = resource_identifier_type_for_belongs_to(parent_object, association_key) + id = resource_identifier_id_for_belongs_to(parent_object, association_key) + + if id + { id: id.to_s, type: type } + else + nil + end + end + def resource_object_for(serializer, options = {}) options[:fields] = @fieldset && @fieldset.fields_for(serializer) @@ -95,14 +120,16 @@ def primary_data_for(serializer, options) end end - def relationship_value_for(serializer, options = {}) - if serializer.respond_to?(:each) - serializer.map { |s| resource_identifier_for(s) } + def relationship_value_for(parent_object, association) + if association.serializer.respond_to?(:each) + association.serializer.map { |serializer| resource_identifier_for(serializer) } else - if options[:virtual_value] - options[:virtual_value] - elsif serializer && serializer.object - resource_identifier_for(serializer) + if association.options[:virtual_value] + association.options[:virtual_value] + elsif parent_object.class.respond_to?(:reflections) && parent_object.class.reflections[association.key.to_s].belongs_to? + resource_identifier_for_belongs_to(parent_object, association.key.to_s) + elsif association.serializer && association.serializer.object + resource_identifier_for(association.serializer) else nil end @@ -110,7 +137,7 @@ def relationship_value_for(serializer, options = {}) end def relationships_for(serializer) - Hash[serializer.associations.map { |association| [ association.key, { data: relationship_value_for(association.serializer, association.options) } ] }] + Hash[serializer.associations.map { |association| [association.key, { data: relationship_value_for(serializer.object, association) }] }] end def included_for(serializer) diff --git a/test/adapter/json_api/belongs_to_test.rb b/test/adapter/json_api/belongs_to_test.rb index 5cb6cdeb0..5ce0062c5 100644 --- a/test/adapter/json_api/belongs_to_test.rb +++ b/test/adapter/json_api/belongs_to_test.rb @@ -150,6 +150,27 @@ def test_include_linked_resources_with_type_name ] assert_equal expected, linked end + + def test_ar_belongs_to_doesnt_load_record + author = ARModels::User.create(name: 'Name 1') + post = ARModels::Post.create(author_id: author.id) + + class << post + def author + fail "should use author_id" + end + end + + hash = ActiveModel::SerializableResource.new(post, adapter: :json_api).serializable_hash + assert_equal({ data: { id: author.id.to_s, type: 'users' } }, hash[:data][:relationships][:author]) + end + + def test_ar_belongs_to_empty + post = ARModels::Post.create + + hash = ActiveModel::SerializableResource.new(post, adapter: :json_api).serializable_hash + assert_equal({ data: nil }, hash[:data][:relationships][:author]) + end end end end diff --git a/test/fixtures/active_record.rb b/test/fixtures/active_record.rb index ab3e4d85c..f60ddab06 100644 --- a/test/fixtures/active_record.rb +++ b/test/fixtures/active_record.rb @@ -8,7 +8,7 @@ t.references :author t.timestamps null: false end - create_table :authors, force: true do |t| + create_table :users, force: true do |t| t.string :name t.timestamps null: false end @@ -23,15 +23,15 @@ module ARModels class Post < ActiveRecord::Base has_many :comments - belongs_to :author + belongs_to :author, class_name: 'User' end class Comment < ActiveRecord::Base belongs_to :post - belongs_to :author + belongs_to :author, class_name: 'User' end - class Author < ActiveRecord::Base + class User < ActiveRecord::Base has_many :posts end @@ -49,7 +49,7 @@ class CommentSerializer < ActiveModel::Serializer belongs_to :author end - class AuthorSerializer < ActiveModel::Serializer + class UserSerializer < ActiveModel::Serializer attributes :id, :name has_many :posts