jsonapi-deserializable/lib/jsonapi/deserializable/resource.rb
2016-11-20 03:31:16 +01:00

111 lines
2.8 KiB
Ruby

require 'jsonapi/deserializable/resource_dsl'
module JSONAPI
module Deserializable
class Resource
include ResourceDSL
class << self
attr_accessor :type_block, :id_block, :attr_blocks,
:has_one_rel_blocks, :has_many_rel_blocks
end
self.attr_blocks = {}
self.has_one_rel_blocks = {}
self.has_many_rel_blocks = {}
def self.inherited(klass)
super
klass.type_block = type_block
klass.id_block = id_block
klass.attr_blocks = attr_blocks.dup
klass.has_one_rel_blocks = has_one_rel_blocks.dup
klass.has_many_rel_blocks = has_many_rel_blocks.dup
end
def self.call(payload)
new(payload).to_h
end
def initialize(payload)
@document = payload
@data = @document['data']
@type = @data['type']
@id = @data['id']
@attributes = @data['attributes'] || {}
@relationships = @data['relationships'] || {}
deserialize!
end
def to_hash
@hash
end
alias to_h to_hash
private
def deserialize!
@hash = {}
deserialize_type!
deserialize_id!
deserialize_attrs!
deserialize_rels!
end
def deserialize_type!
return unless @type && self.class.type_block
instance_exec(@type, &self.class.type_block)
end
def deserialize_id!
return unless @id && self.class.id_block
instance_exec(@id, &self.class.id_block)
end
def deserialize_attrs!
self.class.attr_blocks.each do |attr, block|
next unless @attributes.key?(attr)
instance_exec(@attributes[attr], &block)
end
end
def deserialize_rels!
deserialize_has_one_rels!
deserialize_has_many_rels!
end
def deserialize_has_one_rels!
self.class.has_one_rel_blocks.each do |key, block|
rel = @relationships[key]
next unless rel && (rel['data'].nil? || rel['data'].is_a?(Hash))
deserialize_has_one_rel!(rel, &block)
end
end
def deserialize_has_one_rel!(rel, &block)
id = rel['data'] && rel['data']['id']
type = rel['data'] && rel['data']['type']
instance_exec(rel, id, type, &block)
end
def deserialize_has_many_rels!
self.class.has_many_rel_blocks.each do |key, block|
rel = @relationships[key]
next unless rel && rel['data'].is_a?(Array)
deserialize_has_many_rel!(rel, &block)
end
end
def deserialize_has_many_rel!(rel, &block)
ids = rel['data'].map { |ri| ri['id'] }
types = rel['data'].map { |ri| ri['type'] }
instance_exec(rel, ids, types, &block)
end
def field(hash)
@hash.merge!(hash)
end
end
end
end