mirror of
https://github.com/ditkrg/active_model_serializers.git
synced 2026-01-22 22:06:50 +00:00
Merge pull request #1547 from bf4/jsonapi_renderer
Basic Jsonapi Renderer registration
This commit is contained in:
commit
c7b2916f37
64
lib/active_model_serializers/register_jsonapi_renderer.rb
Normal file
64
lib/active_model_serializers/register_jsonapi_renderer.rb
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
# Based on discussion in https://github.com/rails/rails/pull/23712#issuecomment-184977238,
|
||||||
|
# the JSON API media type will have its own format/renderer.
|
||||||
|
#
|
||||||
|
# > We recommend the media type be registered on its own as jsonapi
|
||||||
|
# when a jsonapi Renderer and deserializer (Http::Parameters::DEFAULT_PARSERS) are added.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
#
|
||||||
|
# ActiveSupport.on_load(:action_controller) do
|
||||||
|
# require 'active_model_serializers/register_jsonapi_renderer'
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# And then in controllers, use `render jsonapi: model` rather than `render json: model, adapter: :json_api`.
|
||||||
|
#
|
||||||
|
# For example, in a controller action, we can:
|
||||||
|
# respond_to do |format|
|
||||||
|
# format.jsonapi { render jsonapi: model }
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# or
|
||||||
|
#
|
||||||
|
# render jsonapi: model
|
||||||
|
#
|
||||||
|
# No wrapper format needed as it does not apply (i.e. no `wrap_parameters format: [jsonapi]`)
|
||||||
|
|
||||||
|
module ActiveModelSerializers::Jsonapi
|
||||||
|
MEDIA_TYPE = 'application/vnd.api+json'.freeze
|
||||||
|
HEADERS = {
|
||||||
|
response: { 'CONTENT_TYPE'.freeze => MEDIA_TYPE },
|
||||||
|
request: { 'ACCEPT'.freeze => MEDIA_TYPE }
|
||||||
|
}.freeze
|
||||||
|
module ControllerSupport
|
||||||
|
def serialize_jsonapi(json, options)
|
||||||
|
options[:adapter] = :json_api
|
||||||
|
options.fetch(:serialization_context) { options[:serialization_context] = ActiveModelSerializers::SerializationContext.new(request) }
|
||||||
|
get_serializer(json, options)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# actionpack/lib/action_dispatch/http/mime_types.rb
|
||||||
|
Mime::Type.register ActiveModelSerializers::Jsonapi::MEDIA_TYPE, :jsonapi
|
||||||
|
|
||||||
|
parsers = Rails::VERSION::MAJOR >= 5 ? ActionDispatch::Http::Parameters : ActionDispatch::ParamsParser
|
||||||
|
media_type = Mime::Type.lookup(ActiveModelSerializers::Jsonapi::MEDIA_TYPE)
|
||||||
|
|
||||||
|
# Proposal: should actually deserialize the JSON API params
|
||||||
|
# to the hash format expected by `ActiveModel::Serializers::JSON`
|
||||||
|
# actionpack/lib/action_dispatch/http/parameters.rb
|
||||||
|
parsers::DEFAULT_PARSERS[media_type] = lambda do |body|
|
||||||
|
data = JSON.parse(body)
|
||||||
|
data = { :_json => data } unless data.is_a?(Hash)
|
||||||
|
data.with_indifferent_access
|
||||||
|
end
|
||||||
|
|
||||||
|
# ref https://github.com/rails/rails/pull/21496
|
||||||
|
ActionController::Renderers.add :jsonapi do |json, options|
|
||||||
|
json = serialize_jsonapi(json, options).to_json(options) unless json.is_a?(String)
|
||||||
|
self.content_type ||= media_type
|
||||||
|
headers.merge! ActiveModelSerializers::Jsonapi::HEADERS[:response]
|
||||||
|
self.response_body = json
|
||||||
|
end
|
||||||
|
|
||||||
|
ActionController::Base.send :include, ActiveModelSerializers::Jsonapi::ControllerSupport
|
||||||
@ -5,6 +5,7 @@ module ActionController
|
|||||||
class JsonApi
|
class JsonApi
|
||||||
class LinkedTest < ActionController::TestCase
|
class LinkedTest < ActionController::TestCase
|
||||||
class LinkedTestController < ActionController::Base
|
class LinkedTestController < ActionController::Base
|
||||||
|
require 'active_model_serializers/register_jsonapi_renderer'
|
||||||
def setup_post
|
def setup_post
|
||||||
ActionController::Base.cache_store.clear
|
ActionController::Base.cache_store.clear
|
||||||
@role1 = Role.new(id: 1, name: 'admin')
|
@role1 = Role.new(id: 1, name: 'admin')
|
||||||
@ -38,49 +39,49 @@ module ActionController
|
|||||||
|
|
||||||
def render_resource_without_include
|
def render_resource_without_include
|
||||||
setup_post
|
setup_post
|
||||||
render json: @post, adapter: :json_api
|
render jsonapi: @post
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_resource_with_include
|
def render_resource_with_include
|
||||||
setup_post
|
setup_post
|
||||||
render json: @post, include: [:author], adapter: :json_api
|
render jsonapi: @post, include: [:author]
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_resource_with_include_of_custom_key_by_original
|
def render_resource_with_include_of_custom_key_by_original
|
||||||
setup_post
|
setup_post
|
||||||
render json: @post, include: [:reviews], adapter: :json_api, serializer: PostWithCustomKeysSerializer
|
render jsonapi: @post, include: [:reviews], serializer: PostWithCustomKeysSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_resource_with_nested_include
|
def render_resource_with_nested_include
|
||||||
setup_post
|
setup_post
|
||||||
render json: @post, include: [comments: [:author]], adapter: :json_api
|
render jsonapi: @post, include: [comments: [:author]]
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_resource_with_nested_has_many_include_wildcard
|
def render_resource_with_nested_has_many_include_wildcard
|
||||||
setup_post
|
setup_post
|
||||||
render json: @post, include: 'author.*', adapter: :json_api
|
render jsonapi: @post, include: 'author.*'
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_resource_with_missing_nested_has_many_include
|
def render_resource_with_missing_nested_has_many_include
|
||||||
setup_post
|
setup_post
|
||||||
@post.author = @author2 # author2 has no roles.
|
@post.author = @author2 # author2 has no roles.
|
||||||
render json: @post, include: [author: [:roles]], adapter: :json_api
|
render jsonapi: @post, include: [author: [:roles]]
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_collection_with_missing_nested_has_many_include
|
def render_collection_with_missing_nested_has_many_include
|
||||||
setup_post
|
setup_post
|
||||||
@post.author = @author2
|
@post.author = @author2
|
||||||
render json: [@post, @post2], include: [author: [:roles]], adapter: :json_api
|
render jsonapi: [@post, @post2], include: [author: [:roles]]
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_collection_without_include
|
def render_collection_without_include
|
||||||
setup_post
|
setup_post
|
||||||
render json: [@post], adapter: :json_api
|
render jsonapi: [@post]
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_collection_with_include
|
def render_collection_with_include
|
||||||
setup_post
|
setup_post
|
||||||
render json: [@post], include: 'author, comments', adapter: :json_api
|
render jsonapi: [@post], include: 'author, comments'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user