Don't memoize association serializer

This commit is contained in:
Jorge Bejar 2014-01-09 15:30:19 -02:00 committed by Santiago Pastorino
parent 3329a43d02
commit df481b2b35
5 changed files with 69 additions and 16 deletions

View File

@ -20,11 +20,11 @@ module ActiveModel
@embedded_key = options[:root] || name @embedded_key = options[:root] || name
serializer = @options[:serializer] serializer = @options[:serializer]
@serializer_class = serializer.is_a?(String) ? serializer.constantize : serializer @serializer_from_options = serializer.is_a?(String) ? serializer.constantize : serializer
end end
attr_reader :name, :embed_ids, :embed_objects attr_reader :name, :embed_ids, :embed_objects
attr_accessor :embed_in_root, :embed_key, :key, :embedded_key, :root_key, :serializer_class, :options attr_accessor :embed_in_root, :embed_key, :key, :embedded_key, :root_key, :serializer_from_options, :options
alias embed_ids? embed_ids alias embed_ids? embed_ids
alias embed_objects? embed_objects alias embed_objects? embed_objects
alias embed_in_root? embed_in_root alias embed_in_root? embed_in_root
@ -34,8 +34,16 @@ module ActiveModel
@embed_objects = embed == :object || embed == :objects @embed_objects = embed == :object || embed == :objects
end end
def serializer_from_object(object)
Serializer.serializer_for(object)
end
def default_serializer
DefaultSerializer
end
def build_serializer(object, options = {}) def build_serializer(object, options = {})
@serializer_class.new(object, options.merge(@options)) serializer_class(object).new(object, options.merge(self.options))
end end
class HasOne < Association class HasOne < Association
@ -45,8 +53,11 @@ module ActiveModel
@key ||= "#{name}_id" @key ||= "#{name}_id"
end end
def serializer_class(object)
serializer_from_options || serializer_from_object(object) || default_serializer
end
def build_serializer(object, options = {}) def build_serializer(object, options = {})
@serializer_class ||= Serializer.serializer_for(object) || DefaultSerializer
options[:_wrap_in_array] = embed_in_root? options[:_wrap_in_array] = embed_in_root?
super super
end end
@ -59,17 +70,29 @@ module ActiveModel
@key ||= "#{name.to_s.singularize}_ids" @key ||= "#{name.to_s.singularize}_ids"
end end
def build_serializer(object, options = {}) def serializer_class(object)
if @serializer_class && !(@serializer_class <= ArraySerializer) if use_array_serializer?
@options[:each_serializer] = @serializer_class ArraySerializer
@serializer_class = ArraySerializer
else else
@serializer_class ||= ArraySerializer serializer_from_options
end
end end
def options
if use_array_serializer?
{ each_serializer: serializer_from_options }.merge! super
else
super super
end end
end end
private
def use_array_serializer?
!serializer_from_options ||
serializer_from_options && !(serializer_from_options <= ArraySerializer)
end
end
end end
end end
end end

View File

@ -78,6 +78,36 @@ module ActiveModel
ensure ensure
PostSerializer._associations[:comments] = @old_association PostSerializer._associations[:comments] = @old_association
end end
def test_embed_object_for_has_one_association_with_nil_value
@association = UserSerializer._associations[:profile]
@old_association = @association.dup
@association.embed = :objects
@user1 = User.new({ name: 'User 1', email: 'email1@server.com' })
@user2 = User.new({ name: 'User 2', email: 'email2@server.com' })
class << @user1
def profile
nil
end
end
class << @user2
def profile
@profile ||= Profile.new(name: 'Name 1', description: 'Desc 1')
end
end
@serializer = ArraySerializer.new([@user1, @user2]) #, root: :posts)
assert_equal([
{ name: "User 1", email: "email1@server.com", profile: nil },
{ name: "User 2", email: "email2@server.com", profile: { name: 'Name 1', description: 'Desc 1' } }
], @serializer.as_json)
ensure
UserSerializer._associations[:profile] = @old_association
end
end end
end end
end end

View File

@ -128,7 +128,7 @@ module ActiveModel
def test_associations_using_a_given_serializer def test_associations_using_a_given_serializer
@association.embed = :ids @association.embed = :ids
@association.embed_in_root = true @association.embed_in_root = true
@association.serializer_class = Class.new(ActiveModel::Serializer) do @association.serializer_from_options = Class.new(ActiveModel::Serializer) do
def content def content
object.read_attribute_for_serialization(:content) + '!' object.read_attribute_for_serialization(:content) + '!'
end end
@ -145,7 +145,7 @@ module ActiveModel
def test_associations_embedding_ids_using_a_given_array_serializer def test_associations_embedding_ids_using_a_given_array_serializer
@association.embed = :ids @association.embed = :ids
@association.embed_in_root = true @association.embed_in_root = true
@association.serializer_class = Class.new(ActiveModel::ArraySerializer) do @association.serializer_from_options = Class.new(ActiveModel::ArraySerializer) do
def serializable_object def serializable_object
{ my_content: ['fake'] } { my_content: ['fake'] }
end end
@ -158,7 +158,7 @@ module ActiveModel
end end
def test_associations_embedding_objects_using_a_given_array_serializer def test_associations_embedding_objects_using_a_given_array_serializer
@association.serializer_class = Class.new(ActiveModel::ArraySerializer) do @association.serializer_from_options = Class.new(ActiveModel::ArraySerializer) do
def serializable_object def serializable_object
{ my_content: ['fake'] } { my_content: ['fake'] }
end end

View File

@ -119,7 +119,7 @@ module ActiveModel
def test_associations_embedding_ids_using_a_given_serializer def test_associations_embedding_ids_using_a_given_serializer
@association.embed = :ids @association.embed = :ids
@association.embed_in_root = true @association.embed_in_root = true
@association.serializer_class = Class.new(ActiveModel::Serializer) do @association.serializer_from_options = Class.new(ActiveModel::Serializer) do
def name def name
'fake' 'fake'
end end
@ -134,7 +134,7 @@ module ActiveModel
end end
def test_associations_embedding_objects_using_a_given_serializer def test_associations_embedding_objects_using_a_given_serializer
@association.serializer_class = Class.new(ActiveModel::Serializer) do @association.serializer_from_options = Class.new(ActiveModel::Serializer) do
def name def name
'fake' 'fake'
end end

View File

@ -31,7 +31,7 @@ module ActiveModel
end end
def test_scope_passed_through def test_scope_passed_through
@association.serializer_class = Class.new(ActiveModel::Serializer) do @association.serializer_from_options = Class.new(ActiveModel::Serializer) do
def name def name
scope scope
end end