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

View File

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

View File

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

View File

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

View File

@ -3,37 +3,141 @@ require 'test_helper'
module ActiveModel
class Serializer
class Configuration
class GlobalTest < Minitest::Test
def test_returns_global_configuration
assert_kind_of Configuration, Configuration.global
end
class Test < Minitest::Test
class ParentConfiguration < Configuration
options :root, :embed_in_root, :embed
def test_global_configuration_returns_the_same_instance
assert_equal Configuration.global.object_id, Configuration.global.object_id
end
def test_global_configuration_has_default_options_set
assert Configuration.default_options.all? do |name, value|
Configuration.global.send(name) == value
end
def default_options
{ embed: :objects }
end
end
class OptionsTest < Minitest::Test
class ChildConfiguration < ParentConfiguration
options :scope
end
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
def test_configuration_has_root_option
assert_equal 'root', @configuration.root
end
def test_configuration_has_embed_option
assert_equal :ids, @configuration.embed
def test_configuration_sets_root_option
@configuration.root = 'other'
assert_equal 'other', @configuration.root
end
def test_configuration_has_embed_in_root_option
assert_equal false, @configuration.embed_in_root
def test_configuration_has_default_embed_option
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

View File

@ -22,7 +22,7 @@ module ActiveModel
end
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({
'profile' => {

View File

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