working on new relationship class
This commit is contained in:
parent
f864099761
commit
7b23adddc4
@ -4,6 +4,7 @@ require 'active_support/core_ext/object'
|
||||
require 'active_support/concern'
|
||||
require 'active_support/inflector'
|
||||
require 'fast_jsonapi/attribute'
|
||||
require 'fast_jsonapi/relationship'
|
||||
require 'fast_jsonapi/serialization_core'
|
||||
|
||||
module FastJsonapi
|
||||
@ -169,38 +170,32 @@ module FastJsonapi
|
||||
|
||||
alias_method :attribute, :attributes
|
||||
|
||||
def add_relationship(name, relationship)
|
||||
def add_relationship(relationship)
|
||||
self.relationships_to_serialize = {} if relationships_to_serialize.nil?
|
||||
self.cachable_relationships_to_serialize = {} if cachable_relationships_to_serialize.nil?
|
||||
self.uncachable_relationships_to_serialize = {} if uncachable_relationships_to_serialize.nil?
|
||||
|
||||
if !relationship[:cached]
|
||||
self.uncachable_relationships_to_serialize[name] = relationship
|
||||
|
||||
if !relationship.cached
|
||||
self.uncachable_relationships_to_serialize[relationship.name] = relationship
|
||||
else
|
||||
self.cachable_relationships_to_serialize[name] = relationship
|
||||
self.cachable_relationships_to_serialize[relationship.name] = relationship
|
||||
end
|
||||
self.relationships_to_serialize[name] = relationship
|
||||
self.relationships_to_serialize[relationship.name] = relationship
|
||||
end
|
||||
|
||||
def has_many(relationship_name, options = {}, &block)
|
||||
name = relationship_name.to_sym
|
||||
hash = create_relationship_hash(relationship_name, :has_many, options, block)
|
||||
add_relationship(name, hash)
|
||||
create_relationship(relationship_name, :has_many, options, block)
|
||||
end
|
||||
|
||||
def has_one(relationship_name, options = {}, &block)
|
||||
name = relationship_name.to_sym
|
||||
hash = create_relationship_hash(relationship_name, :has_one, options, block)
|
||||
add_relationship(name, hash)
|
||||
create_relationship(relationship_name, :has_one, options, block)
|
||||
end
|
||||
|
||||
def belongs_to(relationship_name, options = {}, &block)
|
||||
name = relationship_name.to_sym
|
||||
hash = create_relationship_hash(relationship_name, :belongs_to, options, block)
|
||||
add_relationship(name, hash)
|
||||
create_relationship(relationship_name, :belongs_to, options, block)
|
||||
end
|
||||
|
||||
def create_relationship_hash(base_key, relationship_type, options, block)
|
||||
def create_relationship(base_key, relationship_type, options, block)
|
||||
name = base_key.to_sym
|
||||
if relationship_type == :has_many
|
||||
base_serialization_key = base_key.to_s.singularize
|
||||
@ -211,7 +206,7 @@ module FastJsonapi
|
||||
base_key_sym = name
|
||||
id_postfix = '_id'
|
||||
end
|
||||
{
|
||||
relationship = Relationship.new(
|
||||
key: options[:key] || run_key_transform(base_key),
|
||||
name: name,
|
||||
id_method_name: options[:id_method_name] || "#{base_serialization_key}#{id_postfix}".to_sym,
|
||||
@ -220,10 +215,11 @@ module FastJsonapi
|
||||
object_block: block,
|
||||
serializer: compute_serializer_name(options[:serializer] || base_key_sym),
|
||||
relationship_type: relationship_type,
|
||||
cached: options[:cached] || false,
|
||||
cached: options[:cached],
|
||||
polymorphic: fetch_polymorphic_option(options),
|
||||
conditional_proc: options[:if]
|
||||
}
|
||||
)
|
||||
add_relationship(relationship)
|
||||
end
|
||||
|
||||
def compute_serializer_name(serializer_key)
|
||||
@ -255,8 +251,8 @@ module FastJsonapi
|
||||
parse_include_item(include_item).each do |parsed_include|
|
||||
relationship_to_include = klass.relationships_to_serialize[parsed_include]
|
||||
raise ArgumentError, "#{parsed_include} is not specified as a relationship on #{klass.name}" unless relationship_to_include
|
||||
raise NotImplementedError if relationship_to_include[:polymorphic].is_a?(Hash)
|
||||
klass = relationship_to_include[:serializer].to_s.constantize
|
||||
raise NotImplementedError if relationship_to_include.polymorphic.is_a?(Hash)
|
||||
klass = relationship_to_include.serializer.to_s.constantize
|
||||
end
|
||||
end
|
||||
end
|
||||
|
99
lib/fast_jsonapi/relationship.rb
Normal file
99
lib/fast_jsonapi/relationship.rb
Normal file
@ -0,0 +1,99 @@
|
||||
module FastJsonapi
|
||||
class Relationship
|
||||
attr_reader :key, :name, :id_method_name, :record_type, :object_method_name, :object_block, :serializer, :relationship_type, :cached, :polymorphic, :conditional_proc
|
||||
|
||||
def initialize(
|
||||
key:,
|
||||
name:,
|
||||
id_method_name:,
|
||||
record_type:,
|
||||
object_method_name:,
|
||||
object_block:,
|
||||
serializer:,
|
||||
relationship_type:,
|
||||
cached: false,
|
||||
polymorphic:,
|
||||
conditional_proc:
|
||||
)
|
||||
@key = key
|
||||
@name = name
|
||||
@id_method_name = id_method_name
|
||||
@record_type = record_type
|
||||
@object_method_name = object_method_name
|
||||
@object_block = object_block
|
||||
@serializer = serializer
|
||||
@relationship_type = relationship_type
|
||||
@cached = cached
|
||||
@polymorphic = polymorphic
|
||||
@conditional_proc = conditional_proc
|
||||
end
|
||||
|
||||
def serialize(record, serialization_params, output_hash)
|
||||
if include_relationship?(record, serialization_params)
|
||||
empty_case = relationship_type == :has_many ? [] : nil
|
||||
output_hash[key] = {
|
||||
data: ids_hash_from_record_and_relationship(record, serialization_params) || empty_case
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def include_relationship?(record, serialization_params)
|
||||
if conditional_proc.present?
|
||||
conditional_proc.call(record, serialization_params)
|
||||
else
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
def ids_hash_from_record_and_relationship(record, params = {})
|
||||
return ids_hash(
|
||||
fetch_id(record, params)
|
||||
) unless polymorphic
|
||||
|
||||
return unless associated_object = fetch_associated_object(record, params)
|
||||
|
||||
return associated_object.map do |object|
|
||||
id_hash_from_record object, polymorphic
|
||||
end if associated_object.respond_to? :map
|
||||
|
||||
id_hash_from_record associated_object, polymorphic
|
||||
end
|
||||
|
||||
def id_hash_from_record(record, record_types)
|
||||
# memoize the record type within the record_types dictionary, then assigning to record_type:
|
||||
associated_record_type = record_types[record.class] ||= record.class.name.underscore.to_sym
|
||||
id_hash(record.id, associated_record_type)
|
||||
end
|
||||
|
||||
def ids_hash(ids)
|
||||
return ids.map { |id| id_hash(id, record_type) } if ids.respond_to? :map
|
||||
id_hash(ids, record_type) # ids variable is just a single id here
|
||||
end
|
||||
|
||||
def id_hash(id, associated_record_type, default_return=false)
|
||||
if id.present?
|
||||
{ id: id.to_s, type: record_type }
|
||||
else
|
||||
default_return ? { id: nil, type: associated_record_type } : nil
|
||||
end
|
||||
end
|
||||
|
||||
def fetch_associated_object(record, params)
|
||||
return object_block.call(record, params) unless object_block.nil?
|
||||
record.send(object_method_name)
|
||||
end
|
||||
|
||||
def fetch_id(record, params)
|
||||
unless object_block.nil?
|
||||
object = object_block.call(record, params)
|
||||
|
||||
return object.map(&:id) if object.respond_to? :map
|
||||
return object.try(:id)
|
||||
end
|
||||
|
||||
record.public_send(id_method_name)
|
||||
end
|
||||
end
|
||||
end
|
@ -34,34 +34,6 @@ module FastJsonapi
|
||||
end
|
||||
end
|
||||
|
||||
def ids_hash(ids, record_type)
|
||||
return ids.map { |id| id_hash(id, record_type) } if ids.respond_to? :map
|
||||
id_hash(ids, record_type) # ids variable is just a single id here
|
||||
end
|
||||
|
||||
def id_hash_from_record(record, record_types)
|
||||
# memoize the record type within the record_types dictionary, then assigning to record_type:
|
||||
record_type = record_types[record.class] ||= record.class.name.underscore.to_sym
|
||||
id_hash(record.id, record_type)
|
||||
end
|
||||
|
||||
def ids_hash_from_record_and_relationship(record, relationship, params = {})
|
||||
polymorphic = relationship[:polymorphic]
|
||||
|
||||
return ids_hash(
|
||||
fetch_id(record, relationship, params),
|
||||
relationship[:record_type]
|
||||
) unless polymorphic
|
||||
|
||||
return unless associated_object = fetch_associated_object(record, relationship, params)
|
||||
|
||||
return associated_object.map do |object|
|
||||
id_hash_from_record object, polymorphic
|
||||
end if associated_object.respond_to? :map
|
||||
|
||||
id_hash_from_record associated_object, polymorphic
|
||||
end
|
||||
|
||||
def links_hash(record, params = {})
|
||||
data_links.each_with_object({}) do |(key, method), link_hash|
|
||||
link_hash[key] = if method.is_a?(Proc)
|
||||
@ -82,14 +54,7 @@ module FastJsonapi
|
||||
relationships = relationships_to_serialize if relationships.nil?
|
||||
|
||||
relationships.each_with_object({}) do |(_k, relationship), hash|
|
||||
conditional_proc = relationship[:conditional_proc]
|
||||
if conditional_proc.blank? || conditional_proc.call(record, params)
|
||||
name = relationship[:key]
|
||||
empty_case = relationship[:relationship_type] == :has_many ? [] : nil
|
||||
hash[name] = {
|
||||
data: ids_hash_from_record_and_relationship(record, relationship, params) || empty_case
|
||||
}
|
||||
end
|
||||
relationship.serialize(record, params, hash)
|
||||
end
|
||||
end
|
||||
|
||||
@ -146,12 +111,12 @@ module FastJsonapi
|
||||
items = parse_include_item(include_item)
|
||||
items.each do |item|
|
||||
next unless relationships_to_serialize && relationships_to_serialize[item]
|
||||
conditional_proc = relationships_to_serialize[item][:conditional_proc]
|
||||
conditional_proc = relationships_to_serialize[item].conditional_proc
|
||||
next if conditional_proc && !conditional_proc.call(record, params)
|
||||
raise NotImplementedError if @relationships_to_serialize[item][:polymorphic].is_a?(Hash)
|
||||
record_type = @relationships_to_serialize[item][:record_type]
|
||||
serializer = @relationships_to_serialize[item][:serializer].to_s.constantize
|
||||
relationship_type = @relationships_to_serialize[item][:relationship_type]
|
||||
raise NotImplementedError if @relationships_to_serialize[item].polymorphic.is_a?(Hash)
|
||||
record_type = @relationships_to_serialize[item].record_type
|
||||
serializer = @relationships_to_serialize[item].serializer.to_s.constantize
|
||||
relationship_type = @relationships_to_serialize[item].relationship_type
|
||||
|
||||
included_objects = fetch_associated_object(record, @relationships_to_serialize[item], params)
|
||||
next if included_objects.blank?
|
||||
@ -174,19 +139,8 @@ module FastJsonapi
|
||||
end
|
||||
|
||||
def fetch_associated_object(record, relationship, params)
|
||||
return relationship[:object_block].call(record, params) unless relationship[:object_block].nil?
|
||||
record.send(relationship[:object_method_name])
|
||||
end
|
||||
|
||||
def fetch_id(record, relationship, params)
|
||||
unless relationship[:object_block].nil?
|
||||
object = relationship[:object_block].call(record, params)
|
||||
|
||||
return object.map(&:id) if object.respond_to? :map
|
||||
return object.try(:id)
|
||||
end
|
||||
|
||||
record.public_send(relationship[:id_method_name])
|
||||
return relationship.object_block.call(record, params) unless relationship.object_block.nil?
|
||||
record.send(relationship.object_method_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,6 +1,6 @@
|
||||
RSpec.shared_examples 'returning correct relationship hash' do |serializer, id_method_name, record_type|
|
||||
it 'returns correct relationship hash' do
|
||||
expect(relationship).to be_instance_of(Hash)
|
||||
expect(relationship).to be_instance_of(FastJsonapi::Relationship)
|
||||
expect(relationship.keys).to all(be_instance_of(Symbol))
|
||||
expect(relationship[:serializer]).to be serializer
|
||||
expect(relationship[:id_method_name]).to be id_method_name
|
||||
|
Loading…
x
Reference in New Issue
Block a user