From e1274b2c14cae41d867093699b5b9bb7f291c427 Mon Sep 17 00:00:00 2001 From: Lucas Hosseini Date: Tue, 6 Oct 2015 19:35:09 +0200 Subject: [PATCH] Add support for resource-level JSON API links. --- lib/active_model/serializer.rb | 14 ++++++- .../serializer/adapter/json_api.rb | 23 ++++++++++-- test/adapter/json_api/links_test.rb | 37 +++++++++++++++++++ 3 files changed, 69 insertions(+), 5 deletions(-) create mode 100644 test/adapter/json_api/links_test.rb diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index 643167a77..21aec757f 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -50,6 +50,10 @@ def self.type(type) self._type = type end + def self.links(&block) + self._links_block = block + end + def self.attributes(*attrs) attrs = attrs.first if attrs.first.class == Array @@ -121,8 +125,9 @@ def self.get_serializer_for(klass) end end - attr_accessor :object, :root, :scope + attr_accessor :object, :root, :scope, :links class_attribute :_type, instance_writer: false + class_attribute :_links_block, instance_writer: false def initialize(object, options = {}) self.object = object @@ -136,6 +141,13 @@ def initialize(object, options = {}) define_method scope_name, lambda { scope } end end + + instance_eval(&_links_block) if _links_block + end + + def link(name, value) + self.links ||= {} + self.links[name] = value end def json_key diff --git a/lib/active_model/serializer/adapter/json_api.rb b/lib/active_model/serializer/adapter/json_api.rb index 2792af094..9b29ed957 100644 --- a/lib/active_model/serializer/adapter/json_api.rb +++ b/lib/active_model/serializer/adapter/json_api.rb @@ -93,7 +93,7 @@ def serializable_hash_for_collection(options) if serializer.paginated? hash[:links] ||= {} - hash[:links].update(links_for(serializer, options)) + hash[:links].update(pagination_links_for(serializer, options)) end hash @@ -134,13 +134,24 @@ def resource_identifier_for(serializer) { id: id.to_s, type: type } end + def attributes_for(serializer, fields) + attributes = serializer.attributes.except(:id) + attributes.slice!(*fields) if fields + + attributes + end + def resource_object_for(serializer) cache_check(serializer) do resource_object = resource_identifier_for(serializer) + requested_fields = fieldset && fieldset.fields_for(resource_object[:type]) - attributes = serializer.attributes.except(:id) - attributes.slice!(*requested_fields) if requested_fields + attributes = attributes_for(serializer, requested_fields) resource_object[:attributes] = attributes if attributes.any? + + links = links_for(serializer) + resource_object[:links] = links if links.any? + resource_object end end @@ -200,7 +211,11 @@ def add_included_resources_for(serializer, include_tree, included) end end - def links_for(serializer, options) + def links_for(serializer) + serializer.links || {} + end + + def pagination_links_for(serializer, options) JsonApi::PaginationLinks.new(serializer.object, options[:context]).serializable_hash(options) end end diff --git a/test/adapter/json_api/links_test.rb b/test/adapter/json_api/links_test.rb new file mode 100644 index 000000000..7c79e5d31 --- /dev/null +++ b/test/adapter/json_api/links_test.rb @@ -0,0 +1,37 @@ +require 'test_helper' + +LinkPost = Class.new(Model) +class LinkPostSerializer < ActiveModel::Serializer + belongs_to :link_author +end + +LinkAuthor = Class.new(Model) +class LinkAuthorSerializer < ActiveModel::Serializer + links do + link :self, href: "//example.com/link_author/#{object.id}" + end +end + +module ActiveModel + class Serializer + module Adapter + class JsonApi + class LinksTest < Minitest::Test + def setup + @author = LinkAuthor.new(id: 1337) + end + + def test_resource_links + hash = serializable(@author, adapter: :json_api).serializable_hash + expected = { + self: { + href: '//example.com/link_author/1337' + } + } + assert_equal(expected, hash[:data][:links]) + end + end + end + end + end +end