Skip to content
Closed
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
4 changes: 3 additions & 1 deletion lib/active_model/serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,9 @@ def include!(name, options={})
if association.embed_in_root? && hash.nil?
raise IncludeError.new(self.class, association.name)
elsif association.embed_in_root? && association.embeddable?
merge_association hash, association.root, association.serializables, unique_values
association.roots.each do |root|
merge_association hash, root, association.serializables_for_root(root), unique_values
end
end
elsif association.embed_objects?
node[association.key] = association.serialize
Expand Down
154 changes: 92 additions & 62 deletions lib/active_model/serializer/associations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ def initialize(name, options={}, serializer_options={})
@embed_objects = embed == :object || embed == :objects
@embed_key = options[:embed_key] || :id
@embed_in_root = options[:include]
@polymorphic = options[:polymorphic] || false

serializer = options[:serializer]
@serializer_class = serializer.is_a?(String) ? serializer.constantize : serializer
Expand All @@ -44,7 +45,6 @@ def initialize(name, options={}, serializer_options={})
alias embeddable? object
alias embed_objects? embed_objects
alias embed_ids? embed_ids
alias use_id_key? embed_ids?
alias embed_in_root? embed_in_root

def key
Expand All @@ -59,7 +59,8 @@ def key

private

attr_reader :embed_key, :serializer_class, :options, :serializer_options
attr_reader :embed_key, :serializer_class, :options, :serializer_options, :polymorphic
alias polymorphic? polymorphic

def find_serializable(object)
if serializer_class
Expand All @@ -71,52 +72,116 @@ def find_serializable(object)
end
end

def type_name(object)
object.class.to_s.demodulize.underscore.to_sym
end

def serialize_item(object)
serializable_hash = find_serializable(object).serializable_hash
if polymorphic?
type_name = type_name object
{
:type => type_name,
type_name => serializable_hash
}
else
serializable_hash
end
end

def serialization_id(object)
serializer = find_serializable(object)
if serializer.respond_to?(embed_key)
serializer.send(embed_key)
else
object.read_attribute_for_serialization(embed_key)
end
end

def serialize_id(object)
id = serialization_id object

if polymorphic?
{
type: type_name(object),
id: id
}
else
id
end
end

def use_id_key?
embed_ids? && !polymorphic?
end

class HasMany < Association #:nodoc:
def root
options[:root] || name
def roots
if options[:root]
[options[:root]]
elsif polymorphic?
object.map do |item|
polymorphic_root_for_item(item)
end.uniq
else
[name.to_s.pluralize.to_sym]
end
end

def id_key
"#{name.to_s.singularize}_ids".to_sym
end

def serializables
object.map do |item|
find_serializable(item)
def serializables_for_root(root)
if options[:root] || !polymorphic?
object.map do |item|
find_serializable(item)
end
else
object.select do |item|
polymorphic_root_for_item(item) == root
end.map do |item|
find_serializable(item)
end
end
end

def serialize
object.map do |item|
find_serializable(item).serializable_hash
serialize_item item
if polymorphic?
type_name = type_name item
{
:type => type_name,
type_name => find_serializable(item).serializable_hash
}
else
find_serializable(item).serializable_hash
end
end
end

def serialize_ids
object.map do |item|
serializer = find_serializable(item)
if serializer.respond_to?(embed_key)
serializer.send(embed_key)
else
item.read_attribute_for_serialization(embed_key)
end
serialize_id item
end
end
end

class HasOne < Association #:nodoc:
def initialize(name, options={}, serializer_options={})
super
@polymorphic = options[:polymorphic]
private

def polymorphic_root_for_item(item)
item.class.to_s.demodulize.pluralize.underscore.to_sym
end
end

def root
if root = options[:root]
root
class HasOne < Association #:nodoc:
def roots
if options[:root]
[options[:root]]
elsif polymorphic?
object.class.to_s.pluralize.demodulize.underscore.to_sym
[object.class.to_s.pluralize.demodulize.underscore.to_sym]
else
name.to_s.pluralize.to_sym
[name.to_s.pluralize.to_sym]
end
end

Expand All @@ -128,57 +193,22 @@ def embeddable?
super || !polymorphic?
end

def serializables
def serializables_for_root(root)
value = object && find_serializable(object)
value ? [value] : []
end

def serialize
if object
if polymorphic?
{
:type => polymorphic_key,
polymorphic_key => find_serializable(object).serializable_hash
}
else
find_serializable(object).serializable_hash
end
serialize_item object
end
end

def serialize_ids
if object
serializer = find_serializable(object)
id =
if serializer.respond_to?(embed_key)
serializer.send(embed_key)
else
object.read_attribute_for_serialization(embed_key)
end

if polymorphic?
{
type: polymorphic_key,
id: id
}
else
id
end
serialize_id object
end
end

private

attr_reader :polymorphic
alias polymorphic? polymorphic

def use_id_key?
embed_ids? && !polymorphic?
end

def polymorphic_key
object.class.to_s.demodulize.underscore.to_sym
end
end
end
end
Expand Down
Loading