Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 35 additions & 26 deletions lib/jsonapi/rails/action_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions lib/jsonapi/rails/railtie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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