From fdb15462a0c8c18094e6a9d2258c5917ab82262b Mon Sep 17 00:00:00 2001 From: Lucas Hosseini Date: Mon, 14 Nov 2016 19:49:01 +0100 Subject: [PATCH] Fix deserialization. --- lib/jsonapi/rails/action_controller.rb | 61 +++++++++++++++----------- lib/jsonapi/rails/railtie.rb | 1 + 2 files changed, 36 insertions(+), 26 deletions(-) diff --git a/lib/jsonapi/rails/action_controller.rb b/lib/jsonapi/rails/action_controller.rb index 861318b..320ecad 100644 --- a/lib/jsonapi/rails/action_controller.rb +++ b/lib/jsonapi/rails/action_controller.rb @@ -7,54 +7,63 @@ module ActionController def self.included(base) base.class_eval do extend ClassMethods - prepend InstanceMethods end end module ClassMethods - def deserializable_resource(key, klass = nil, &block) + def deserializable_resource(key, *args, &block) + klass = args.shift unless args.first.is_a?(Hash) + options = args.first || {} if klass.nil? klass = Class.new(JSONAPI::Deserializable::Resource, &block) end - @deserializable_key = key - @deserializable_class = klass - @deserializable_parser = JSONAPI::Parser::Resource + use DeserializeResource, key, klass, options end - def deserializable_relationship(key, klass = nil, &block) + def deserializable_relationship(key, *args, &block) + klass = args.shift unless args.first.is_a?(Hash) + options = args.first || {} if klass.nil? klass = Class.new(JSONAPI::Deserializable::Relationship, &block) end + use DeserializeResource, key, klass, options + end + end + + class DeserializationMiddleware + JSONAPI_KEYS = %w(data meta links jsonapi).freeze + def initialize(app, key, klass) + @app = app @deserializable_key = key @deserializable_class = klass - @deserializable_parser = JSONAPI::Parser::Relationship end - def deserializable_class - @deserializable_class - end + def call(env) + request = Rack::Request.new(env) + body = request.params.slice(*JSONAPI_KEYS) + parser.parse!(body) + deserialized_hash = @deserializable_class.call(body) + jsonapi = {} + JSONAPI_KEYS.each do |key| + next unless request.params.key?(key) + jsonapi[key.to_sym] = request.delete_param(key) + end + request.update_param(:_jsonapi, jsonapi) + request.update_param(@deserializable_key, deserialized_hash) - def deserializable_key - @deserializable_key + @app.call(env) end + end - def deserializable_parser - @deserializable_parser + class DeserializeResource < DeserializationMiddleware + def parser + JSONAPI::Parser::Resource end end - module InstanceMethods - def params - params = super - key = self.class.deserializable_key - return params if body.key?(key) - parser = self.class.deserializable_parser - return params unless parser - - parser.parse!(body) - deserializable_class = self.class.deserializable_class - - params.merge!(key => deserializable_class.call(params)) + class DeserializeRelationship < DeserializationMiddleware + def parser + JSONAPI::Parser::Relationship end end end diff --git a/lib/jsonapi/rails/railtie.rb b/lib/jsonapi/rails/railtie.rb index 4d5ef28..c40a8d5 100644 --- a/lib/jsonapi/rails/railtie.rb +++ b/lib/jsonapi/rails/railtie.rb @@ -39,5 +39,6 @@ class Railtie < ::Rails::Railtie end ActiveSupport.on_load(:action_controller) do + require 'jsonapi/rails/action_controller' include JSONAPI::Rails::ActionController end