Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
Adrian Mugnolo and Santiago Pastorino authored and spastorino committed Jan 15, 2014
1 parent 1e5ea0b commit eb9f68b
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 82 deletions.
9 changes: 2 additions & 7 deletions lib/active_model/array_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,7 @@ class ArraySerializer

class << self
def configuration
@configuration ||=
if self == ArraySerializer
Serializer::Configuration.global
else
superclass.configuration.build
end
@configuration ||= Serializer::ClassConfiguration.new super
end
end

Expand All @@ -25,7 +20,7 @@ def configuration

def initialize(object, options = {})
@object = object
@configuration = self.class.configuration.build options
@configuration = Serializer::ArrayConfiguration.new self.class.configuration, options
end

def json_key
Expand Down
2 changes: 1 addition & 1 deletion lib/active_model/default_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class DefaultSerializer

def initialize(object, options = nil)
@object = object
@configuration = Serializer::Configuration::Null.instance
@configuration = Serializer::InstanceConfiguration.new nil
end

def as_json(options = {})
Expand Down
10 changes: 10 additions & 0 deletions lib/active_model/serializable.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
module ActiveModel
module Serializable
def self.included(base)
base.extend ClassMethods
end

def as_json(options={})
if root = options.fetch(:root, json_key)
hash = { root => serializable_object }
Expand All @@ -21,5 +25,11 @@ def serializable_data
def embedded_in_root_associations
{}
end

module ClassMethods
def configuration
Serializer::GlobalConfiguration.instance
end
end
end
end
10 changes: 3 additions & 7 deletions lib/active_model/serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def serializer_for(resource)
end
end

attr_writer :configuration
attr_accessor :_attributes, :_associations

def root_name
Expand All @@ -49,12 +50,7 @@ def root_name
def_delegators :dsl, :attributes, :has_one, :has_many, :embed, :root

def configuration
@configuration ||=
if self == Serializer
Configuration.global
else
superclass.configuration.build
end
@configuration ||= ClassConfiguration.new super
end

private
Expand All @@ -72,7 +68,7 @@ def dsl

def initialize(object, options = {})
@object = object
@configuration = self.class.configuration.build options
@configuration = InstanceConfiguration.new self.class.configuration, options
end

def json_key
Expand Down
97 changes: 46 additions & 51 deletions lib/active_model/serializer/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,77 +3,70 @@
module ActiveModel
class Serializer
class Configuration
class Null
include Singleton

def method_missing(*)
nil
end

def respond_to?(*)
true
class << self
def options(*names)
names.each do |name|
attr_writer name

define_method name do
option name
end
end
end
alias option options
end

attr_accessor :parent

class << self
def global
@global ||= new default_options
end
def initialize(parent, options = {})
self.parent = parent

def default_options
{ embed: :objects, meta_key: :meta }
default_options.merge!(options).each do |name, value|
send "#{name}=", value
end
end

def build(options = {})
self.class.new options, self
def default_options
{}
end

attr_reader :scope, :each_serializer, :resource_name
attr_writer :root, :meta, :meta_key
attr_accessor :wrap_in_array

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]
end
private

def root
return_first @root, parent.root
def own_option(name)
instance_variable_get "@#{name}"
end

def embed
return_first @embed, parent.embed
def parent_option(name)
parent.send name if parent.respond_to? name
end

def embed_in_root
return_first @embed_in_root, parent.embed_in_root
def option(name)
value = own_option name
value.nil? ? parent_option(name) : value
end
end

def meta_key
return_first @meta_key, parent.meta_key
class SerializerConfiguration < Configuration
options :root, :embed, :embed_in_root

def default_options
{ embed: :objects }
end
end

def meta
return_first @meta, parent.meta
class GlobalConfiguration < SerializerConfiguration
include Singleton

def initialize
super nil
end
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
Expand All @@ -85,16 +78,18 @@ def embed_objects
def embed_ids
[:ids, :id].include? embed
end
end

private
class InstanceConfiguration < ClassConfiguration
options :scope, :meta, :meta_key, :wrap_in_array

def read_option(options, name)
options[name] || false if options.has_key? name
def default_options
super.merge! meta_key: :meta
end
end

def return_first(*values)
values.compact.first
end
class ArrayConfiguration < InstanceConfiguration
options :each_serializer, :resource_name
end
end
end
134 changes: 119 additions & 15 deletions test/unit/active_model/serializer/configuration_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,141 @@
module ActiveModel
class Serializer
class Configuration
class GlobalTest < Minitest::Test
def test_returns_global_configuration
assert_kind_of Configuration, Configuration.global
class Test < Minitest::Test
class ParentConfiguration < Configuration
options :root, :embed_in_root, :embed

def default_options
{ embed: :objects }
end
end

def test_global_configuration_returns_the_same_instance
assert_equal Configuration.global.object_id, Configuration.global.object_id
class ChildConfiguration < ParentConfiguration
options :scope
end

def test_global_configuration_has_default_options_set
assert Configuration.default_options.all? do |name, value|
Configuration.global.send(name) == value
end
def setup
@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 OptionsTest < Minitest::Test
class SerializerConfiguration
class Test < Minitest::Test
def setup
@configuration = Configuration.global.build(root: 'root', embed: :ids, embed_in_root: false)
@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_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_embed_in_root_option
assert_equal false, @configuration.embed_in_root
def test_configuration_has_resource_name_option
assert_equal 'posts', @configuration.resource_name
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion test/unit/active_model/serializer/meta_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def test_meta
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' => {
Expand Down

0 comments on commit eb9f68b

Please sign in to comment.