mirror of
https://github.com/ditkrg/active_model_serializers.git
synced 2026-01-23 06:16:50 +00:00
Start cleaning up serializers to support
include/exclude functionality. This process involves building a few lower-level primitives so not as much logic is hardcoded in monolithic helper methods.
This commit is contained in:
parent
ab1a4074ba
commit
f9d0259340
@ -94,44 +94,44 @@ module ActiveModel
|
|||||||
end
|
end
|
||||||
|
|
||||||
class HasMany < Config #:nodoc:
|
class HasMany < Config #:nodoc:
|
||||||
|
alias plural_key key
|
||||||
|
|
||||||
def serialize(collection, scope, context, options)
|
def serialize(collection, scope, context, options)
|
||||||
array = collection.map do |item|
|
collection.map do |item|
|
||||||
find_serializable(item, scope, context, options).as_json(:root => false)
|
find_serializable(item, scope, context, options).as_json(:root => false)
|
||||||
end
|
end
|
||||||
{ key => array }
|
|
||||||
end
|
end
|
||||||
|
|
||||||
alias serialize_many serialize
|
alias serialize_many serialize
|
||||||
|
|
||||||
def serialize_ids(collection, scope)
|
def serialize_ids(collection, scope)
|
||||||
# Use pluck or select_columns if available
|
# Use pluck or select_columns if available
|
||||||
# return collection.ids if collection.respond_to?(:ids)
|
# return collection.ids if collection.respond_to?(:ids)
|
||||||
|
|
||||||
array = collection.map do |item|
|
collection.map do |item|
|
||||||
item.read_attribute_for_serialization(:id)
|
item.read_attribute_for_serialization(:id)
|
||||||
end
|
end
|
||||||
|
|
||||||
{ key => array }
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class HasOne < Config #:nodoc:
|
class HasOne < Config #:nodoc:
|
||||||
|
def plural_key
|
||||||
|
key.to_s.pluralize.to_sym
|
||||||
|
end
|
||||||
|
|
||||||
def serialize(object, scope, context, options)
|
def serialize(object, scope, context, options)
|
||||||
{ key => object && find_serializable(object, scope, context, options).as_json(:root => false) }
|
object && find_serializable(object, scope, context, options).as_json(:root => false)
|
||||||
end
|
end
|
||||||
|
|
||||||
def serialize_many(object, scope, context, options)
|
def serialize_many(object, scope, context, options)
|
||||||
key = self.key.to_s.pluralize.to_sym
|
|
||||||
value = object && find_serializable(object, scope, context, options).as_json(:root => false)
|
value = object && find_serializable(object, scope, context, options).as_json(:root => false)
|
||||||
value = value ? [value] : []
|
value ? [value] : []
|
||||||
{ key => value }
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def serialize_ids(object, scope)
|
def serialize_ids(object, scope)
|
||||||
if object
|
if object
|
||||||
{ key => object.read_attribute_for_serialization(:id) }
|
object.read_attribute_for_serialization(:id)
|
||||||
else
|
else
|
||||||
{ key => nil }
|
nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -307,15 +307,41 @@ module ActiveModel
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def include!(key, options={})
|
||||||
|
embed = options[:embed]
|
||||||
|
root_embed = options[:include]
|
||||||
|
hash = options[:hash]
|
||||||
|
node = options[:node]
|
||||||
|
value = options[:value]
|
||||||
|
serializer = options[:serializer]
|
||||||
|
scope = options[:scope]
|
||||||
|
|
||||||
|
association = Associations::HasMany.new(key, { :serializer => serializer })
|
||||||
|
|
||||||
|
if embed == :ids
|
||||||
|
node[key] = association.serialize_ids(value, scope)
|
||||||
|
|
||||||
|
if root_embed
|
||||||
|
merge_association hash, key, association.serialize_many(value, scope, self, {})
|
||||||
|
end
|
||||||
|
elsif embed == :objects
|
||||||
|
node[key] = association.serialize(value, scope)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Merge associations for embed case by always adding
|
# Merge associations for embed case by always adding
|
||||||
# root associations to the given hash.
|
# root associations to the given hash.
|
||||||
def merge_associations(hash, associations)
|
def merge_associations(hash, associations)
|
||||||
associations.each do |key, value|
|
associations.each do |key, value|
|
||||||
if hash[key]
|
merge_association(hash, key, value)
|
||||||
hash[key] |= value
|
end
|
||||||
elsif value
|
end
|
||||||
hash[key] = value
|
|
||||||
end
|
def merge_association(hash, key, value)
|
||||||
|
if hash[key]
|
||||||
|
hash[key] |= value
|
||||||
|
elsif value
|
||||||
|
hash[key] = value
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -326,7 +352,7 @@ module ActiveModel
|
|||||||
|
|
||||||
_associations.each do |association|
|
_associations.each do |association|
|
||||||
associated_object = send(association.name)
|
associated_object = send(association.name)
|
||||||
hash.merge! association.serialize(associated_object, scope, self, :hash => @hash)
|
hash[association.key] = association.serialize(associated_object, scope, self, :hash => @hash)
|
||||||
end
|
end
|
||||||
|
|
||||||
hash
|
hash
|
||||||
@ -337,7 +363,7 @@ module ActiveModel
|
|||||||
|
|
||||||
_associations.each do |association|
|
_associations.each do |association|
|
||||||
associated_object = send(association.name)
|
associated_object = send(association.name)
|
||||||
hash.merge! association.serialize_many(associated_object, scope, self, :hash => @hash)
|
hash[association.plural_key] = association.serialize_many(associated_object, scope, self, :hash => @hash)
|
||||||
end
|
end
|
||||||
|
|
||||||
hash
|
hash
|
||||||
@ -350,7 +376,7 @@ module ActiveModel
|
|||||||
|
|
||||||
_associations.each do |association|
|
_associations.each do |association|
|
||||||
associated_object = send(association.name)
|
associated_object = send(association.name)
|
||||||
hash.merge! association.serialize_ids(associated_object, scope)
|
hash[association.key] = association.serialize_ids(associated_object, scope)
|
||||||
end
|
end
|
||||||
|
|
||||||
hash
|
hash
|
||||||
|
|||||||
67
test/association_test.rb
Normal file
67
test/association_test.rb
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
require "test_helper"
|
||||||
|
|
||||||
|
class SerializerTest < ActiveModel::TestCase
|
||||||
|
def def_serializer(&block)
|
||||||
|
Class.new(ActiveModel::Serializer, &block)
|
||||||
|
end
|
||||||
|
|
||||||
|
class Model
|
||||||
|
def initialize(hash={})
|
||||||
|
@attributes = hash
|
||||||
|
end
|
||||||
|
|
||||||
|
def read_attribute_for_serialization(name)
|
||||||
|
@attributes[name]
|
||||||
|
end
|
||||||
|
|
||||||
|
def as_json(*)
|
||||||
|
{ :model => "Model" }
|
||||||
|
end
|
||||||
|
|
||||||
|
def method_missing(meth, *args)
|
||||||
|
if meth.to_s =~ /^(.*)=$/
|
||||||
|
@attributes[$1.to_sym] = args[0]
|
||||||
|
elsif @attributes.key?(meth)
|
||||||
|
@attributes[meth]
|
||||||
|
else
|
||||||
|
super
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_include_associations
|
||||||
|
post = Model.new(:title => "New Post", :body => "Body")
|
||||||
|
comment = Model.new(:id => 1, :body => "ZOMG A COMMENT")
|
||||||
|
post.comments = [ comment ]
|
||||||
|
|
||||||
|
comment_serializer_class = def_serializer do
|
||||||
|
attributes :body
|
||||||
|
end
|
||||||
|
|
||||||
|
post_serializer_class = def_serializer do
|
||||||
|
attributes :title, :body
|
||||||
|
end
|
||||||
|
|
||||||
|
post_serializer = post_serializer_class.new(post, nil)
|
||||||
|
|
||||||
|
hash = {}
|
||||||
|
root_hash = {}
|
||||||
|
post_serializer.include! :comments,
|
||||||
|
:embed => :ids,
|
||||||
|
:include => true,
|
||||||
|
:hash => root_hash,
|
||||||
|
:node => hash,
|
||||||
|
:value => post.comments,
|
||||||
|
:serializer => comment_serializer_class
|
||||||
|
|
||||||
|
assert_equal({
|
||||||
|
:comments => [ 1 ]
|
||||||
|
}, hash)
|
||||||
|
|
||||||
|
assert_equal({
|
||||||
|
:comments => [
|
||||||
|
{ :body => "ZOMG A COMMENT" }
|
||||||
|
]
|
||||||
|
}, root_hash)
|
||||||
|
end
|
||||||
|
end
|
||||||
Loading…
Reference in New Issue
Block a user