Split Configuration object

This commit is contained in:
Adrian Mugnolo and Santiago Pastorino 2014-01-13 17:43:59 -02:00 committed by Santiago Pastorino
parent 1e5ea0b356
commit 1a26a089d5
7 changed files with 190 additions and 92 deletions

View File

@ -7,13 +7,14 @@ module ActiveModel
include Serializable include Serializable
class << self class << self
def inherited(subclass)
subclass.configuration = Serializer::ClassConfiguration.new configuration
end
attr_writer :configuration
def configuration def configuration
@configuration ||= @configuration ||= Serializer::ClassConfiguration.new Serializer::GlobalConfiguration.instance
if self == ArraySerializer
Serializer::Configuration.global
else
superclass.configuration.build
end
end end
end end
@ -25,7 +26,7 @@ module ActiveModel
def initialize(object, options = {}) def initialize(object, options = {})
@object = object @object = object
@configuration = self.class.configuration.build options @configuration = Serializer::ArrayConfiguration.new self.class.configuration, options
end end
def json_key def json_key

View File

@ -11,7 +11,7 @@ module ActiveModel
def initialize(object, options = nil) def initialize(object, options = nil)
@object = object @object = object
@configuration = Serializer::Configuration::Null.instance @configuration = Serializer::InstanceConfiguration.new nil
end end
def as_json(options = {}) def as_json(options = {})

View File

@ -11,9 +11,10 @@ module ActiveModel
include Serializable include Serializable
class << self class << self
def inherited(base) def inherited(subclass)
base._attributes = (_attributes || []).dup subclass.configuration = ClassConfiguration.new configuration
base._associations = (_associations || {}).dup subclass._attributes = (_attributes || []).dup
subclass._associations = (_associations || {}).dup
end end
if RUBY_VERSION >= '2.0' if RUBY_VERSION >= '2.0'
@ -38,6 +39,12 @@ module ActiveModel
end end
end end
attr_writer :configuration
def configuration
@configuration ||= ClassConfiguration.new GlobalConfiguration.instance
end
attr_accessor :_attributes, :_associations attr_accessor :_attributes, :_associations
def root_name def root_name
@ -48,15 +55,6 @@ module ActiveModel
def_delegators :dsl, :attributes, :has_one, :has_many, :embed, :root def_delegators :dsl, :attributes, :has_one, :has_many, :embed, :root
def configuration
@configuration ||=
if self == Serializer
Configuration.global
else
superclass.configuration.build
end
end
private private
def dsl def dsl
@ -72,7 +70,7 @@ module ActiveModel
def initialize(object, options = {}) def initialize(object, options = {})
@object = object @object = object
@configuration = self.class.configuration.build options @configuration = InstanceConfiguration.new self.class.configuration, options
end end
def json_key def json_key

View File

@ -3,77 +3,70 @@ require 'singleton'
module ActiveModel module ActiveModel
class Serializer class Serializer
class Configuration class Configuration
class Null class << self
include Singleton def options(*names)
names.each do |name|
attr_writer name
def method_missing(*) define_method name do
nil option name
end end
end
def respond_to?(*)
true
end end
alias option options
end end
attr_accessor :parent attr_accessor :parent
class << self def initialize(parent, options = {})
def global self.parent = parent
@global ||= new default_options
end
def default_options default_options.merge!(options).each do |name, value|
{ embed: :objects, meta_key: :meta } send "#{name}=", value
end end
end end
def build(options = {}) def default_options
self.class.new options, self {}
end end
attr_reader :scope, :each_serializer, :resource_name private
attr_writer :root, :meta, :meta_key
attr_accessor :wrap_in_array
def initialize(options = {}, parent = Null.instance) def own_option(name)
@parent = parent instance_variable_get "@#{name}"
@root = read_option options, :root
@embed = read_option options, :embed
@embed_in_root = read_option options, :embed_in_root
@scope = options[:scope]
@meta_key = read_option options, :meta_key
@meta = read_option options, meta_key
@wrap_in_array = options[:_wrap_in_array]
@each_serializer = options[:each_serializer]
@resource_name = options[:resource_name]
end end
def root def parent_option(name)
return_first @root, parent.root parent.send name if parent.respond_to? name
end end
def embed def option(name)
return_first @embed, parent.embed value = own_option name
value.nil? ? parent_option(name) : value
end end
end
def embed_in_root class SerializerConfiguration < Configuration
return_first @embed_in_root, parent.embed_in_root options :root, :embed, :embed_in_root
def default_options
{ embed: :objects }
end end
end
def meta_key class GlobalConfiguration < SerializerConfiguration
return_first @meta_key, parent.meta_key include Singleton
def initialize
super nil
end end
end
def meta class ClassConfiguration < SerializerConfiguration
return_first @meta, parent.meta
end
# FIXME: Get rid of this mess.
def embed_objects=(value) def embed_objects=(value)
@embed = :objects if value @embed = :objects if value
end end
# FIXME: Get rid of this mess.
def embed_ids=(value) def embed_ids=(value)
@embed = :ids if value @embed = :ids if value
end end
@ -85,16 +78,18 @@ module ActiveModel
def embed_ids def embed_ids
[:ids, :id].include? embed [:ids, :id].include? embed
end end
end
private class InstanceConfiguration < ClassConfiguration
options :scope, :meta, :meta_key, :wrap_in_array, :serializer, :prefixes, :template, :layout
def read_option(options, name) def default_options
options[name] || false if options.has_key? name super.merge! meta_key: :meta
end end
end
def return_first(*values) class ArrayConfiguration < InstanceConfiguration
values.compact.first options :each_serializer, :resource_name
end
end end
end end
end end

View File

@ -3,37 +3,141 @@ require 'test_helper'
module ActiveModel module ActiveModel
class Serializer class Serializer
class Configuration class Configuration
class GlobalTest < Minitest::Test class Test < Minitest::Test
def test_returns_global_configuration class ParentConfiguration < Configuration
assert_kind_of Configuration, Configuration.global options :root, :embed_in_root, :embed
end
def test_global_configuration_returns_the_same_instance def default_options
assert_equal Configuration.global.object_id, Configuration.global.object_id { embed: :objects }
end
def test_global_configuration_has_default_options_set
assert Configuration.default_options.all? do |name, value|
Configuration.global.send(name) == value
end end
end end
end
class OptionsTest < Minitest::Test class ChildConfiguration < ParentConfiguration
options :scope
end
def setup def setup
@configuration = Configuration.global.build(root: 'root', embed: :ids, embed_in_root: false) @parent = ParentConfiguration.new nil, root: 'root', embed_in_root: true
@child = ChildConfiguration.new @parent, root: 'other'
end
def test_configuration_has_root_option
assert_equal 'root', @parent.root
end
def test_parent_has_default_embed_option
assert_equal :objects, @parent.embed
end
def test_child_returns_own_root_option
assert_equal 'other', @child.root
end
def test_child_returns_parent_embed_in_root_option
assert_equal true, @child.embed_in_root
end
def test_child_returns_nil_for_non_existing_parent_option
assert_equal nil, @child.scope
end
end
end
class SerializerConfiguration
class Test < Minitest::Test
def setup
@configuration = SerializerConfiguration.new nil, root: 'root'
end
def test_configuration_inherits_from_base_class
assert_kind_of Configuration, @configuration
end end
def test_configuration_has_root_option def test_configuration_has_root_option
assert_equal 'root', @configuration.root assert_equal 'root', @configuration.root
end end
def test_configuration_has_embed_option def test_configuration_sets_root_option
assert_equal :ids, @configuration.embed @configuration.root = 'other'
assert_equal 'other', @configuration.root
end end
def test_configuration_has_embed_in_root_option def test_configuration_has_default_embed_option
assert_equal false, @configuration.embed_in_root assert_equal :objects, @configuration.embed
end
end
end
class GlobalConfiguration
class Test < Minitest::Test
def setup
@configuration = GlobalConfiguration.instance
end
def test_configuration_inherits_from_base_class
assert_kind_of Configuration, @configuration
end
def test_returns_singleton_configuration
other = GlobalConfiguration.instance
assert @configuration == other, "instances don't match"
end
end
end
class ClassConfiguration
class Test < Minitest::Test
def setup
@configuration = ClassConfiguration.new nil, root: 'root'
end
def test_configuration_inherits_from_base_class
assert_kind_of Configuration, @configuration
end
def test_configuration_has_root_option
assert_equal 'root', @configuration.root
end
def test_configuration_sets_root_option
@configuration.root = 'other'
assert_equal 'other', @configuration.root
end
def test_configuration_has_default_embed_option
assert_equal :objects, @configuration.embed
end
end
end
class InstanceConfiguration
class Test < Minitest::Test
def setup
@configuration = InstanceConfiguration.new nil, scope: :current_user
end
def test_configuration_inherits_from_base_class
assert_kind_of ClassConfiguration, @configuration
end
def test_configuration_has_root_option
assert_equal :current_user, @configuration.scope
end
end
end
class ArrayConfiguration
class Test < Minitest::Test
def setup
@configuration = ArrayConfiguration.new nil, resource_name: 'posts'
end
def test_configuration_inherits_from_base_class
assert_kind_of Configuration, @configuration
end
def test_configuration_has_resource_name_option
assert_equal 'posts', @configuration.resource_name
end end
end end
end end

View File

@ -22,7 +22,7 @@ module ActiveModel
end end
def test_meta_using_meta_key def test_meta_using_meta_key
profile_serializer = ProfileSerializer.new(@profile, root: 'profile', meta_key: :my_meta, my_meta: { total: 10 }) profile_serializer = ProfileSerializer.new(@profile, root: 'profile', meta_key: :my_meta, meta: { total: 10 })
assert_equal({ assert_equal({
'profile' => { 'profile' => {

View File

@ -58,10 +58,10 @@ module ActiveModel
def test_root_inheritance def test_root_inheritance
ProfileSerializer.root 'profile' ProfileSerializer.root 'profile'
inherited_serializer_klass = Class.new(ProfileSerializer) inherited_serializer_klass = Class.new ProfileSerializer
inherited_serializer_klass.root 'inherited_profile' inherited_serializer_klass.root 'inherited_profile'
another_inherited_serializer_klass = Class.new(ProfileSerializer) another_inherited_serializer_klass = Class.new ProfileSerializer
assert_equal('inherited_profile', assert_equal('inherited_profile',
inherited_serializer_klass.configuration.root) inherited_serializer_klass.configuration.root)