Refactor: introduce lazy association

This commit is contained in:
Benjamin Fleischer
2017-04-23 16:48:05 -05:00
parent 34d55e4729
commit 7697d9f5ec
7 changed files with 98 additions and 49 deletions

View File

@@ -1,3 +1,5 @@
require 'active_model/serializer/lazy_association'
module ActiveModel
class Serializer
# This class holds all information about serializer's association.
@@ -10,14 +12,22 @@ module ActiveModel
# Association.new(:comments, { serializer: CommentSummarySerializer })
#
class Association < Field
attr_reader :lazy_association
delegate :include_data?, :virtual_value, to: :lazy_association
def initialize(*)
super
@lazy_association = LazyAssociation.new(name, options, block)
end
# @return [Symbol]
def key
options.fetch(:key, name)
end
# @return [ActiveModel::Serializer, nil]
def serializer
options[:serializer]
# @return [True,False]
def key?
options.key?(:key)
end
# @return [Hash]
@@ -30,21 +40,30 @@ module ActiveModel
options[:meta]
end
def polymorphic?
true == options[:polymorphic]
end
# @api private
def serializable_hash(adapter_options, adapter_instance)
return options[:virtual_value] if options[:virtual_value]
object = serializer && serializer.object
return unless object
association_serializer = lazy_association.serializer
return virtual_value if virtual_value
association_object = association_serializer && association_serializer.object
return unless association_object
serialization = serializer.serializable_hash(adapter_options, {}, adapter_instance)
serialization = association_serializer.serializable_hash(adapter_options, {}, adapter_instance)
if options[:polymorphic] && serialization
polymorphic_type = object.class.name.underscore
if polymorphic? && serialization
polymorphic_type = association_object.class.name.underscore
serialization = { type: polymorphic_type, polymorphic_type.to_sym => serialization }
end
serialization
end
private
delegate :reflection, to: :lazy_association
end
end
end

View File

@@ -193,12 +193,13 @@ module ActiveModel
cache_keys << object_cache_key(serializer, adapter_instance)
serializer.associations(include_directive).each do |association|
if association.serializer.respond_to?(:each)
association.serializer.each do |sub_serializer|
association_serializer = association.lazy_association.serializer
if association_serializer.respond_to?(:each)
association_serializer.each do |sub_serializer|
cache_keys << object_cache_key(sub_serializer, adapter_instance)
end
else
cache_keys << object_cache_key(association.serializer, adapter_instance)
cache_keys << object_cache_key(association_serializer, adapter_instance)
end
end
end

View File

@@ -0,0 +1,22 @@
module ActiveModel
class Serializer
class LazyAssociation < Field
def serializer
options[:serializer]
end
def include_data?
options[:include_data]
end
def virtual_value
options[:virtual_value]
end
def reflection
options[:reflection]
end
end
end
end

View File

@@ -170,7 +170,11 @@ module ActiveModel
end
association_block = nil
Association.new(name, reflection_options, association_block)
reflection_options[:reflection] = self
reflection_options[:parent_serializer] = parent_serializer
reflection_options[:parent_serializer_options] = parent_serializer_options
reflection_options[:include_slice] = include_slice
Association.new(name, reflection_options, block)
end
protected

View File

@@ -257,7 +257,7 @@ module ActiveModelSerializers
def process_relationships(serializer, include_slice)
serializer.associations(include_slice).each do |association|
process_relationship(association.serializer, include_slice[association.key])
process_relationship(association.lazy_association.serializer, include_slice[association.key])
end
end

View File

@@ -15,9 +15,7 @@ module ActiveModelSerializers
def as_json
hash = {}
if association.options[:include_data]
hash[:data] = data_for(association)
end
hash[:data] = data_for(association) if association.include_data?
links = links_for(association)
hash[:links] = links if links.any?
@@ -36,10 +34,10 @@ module ActiveModelSerializers
private
def data_for(association)
serializer = association.serializer
serializer = association.lazy_association.serializer
if serializer.respond_to?(:each)
serializer.map { |s| ResourceIdentifier.new(s, serializable_resource_options).as_json }
elsif (virtual_value = association.options[:virtual_value])
elsif (virtual_value = association.virtual_value)
virtual_value
elsif serializer && serializer.object
ResourceIdentifier.new(serializer, serializable_resource_options).as_json