Skip to content

Commit

Permalink
Merge 4485072 into 58ebf96
Browse files Browse the repository at this point in the history
  • Loading branch information
NullVoxPopuli committed Sep 11, 2016
2 parents 58ebf96 + 4485072 commit ae3c820
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 10 deletions.
14 changes: 4 additions & 10 deletions lib/active_model/serializer.rb
Expand Up @@ -60,16 +60,10 @@ class << self

# @api private
def self.serializer_lookup_chain_for(klass)
chain = []

resource_class_name = klass.name.demodulize
resource_namespace = klass.name.deconstantize
serializer_class_name = "#{resource_class_name}Serializer"

chain.push("#{name}::#{serializer_class_name}") if self != ActiveModel::Serializer
chain.push("#{resource_namespace}::#{serializer_class_name}")

chain
lookups = ActiveModelSerializers.config.serializer_lookup_chain
Array[*lookups].map do |lookup|
lookup.call(klass, self)
end.flatten.compact
end

# Used to cache serializer name => serializer class
Expand Down
25 changes: 25 additions & 0 deletions lib/active_model/serializer/concerns/configuration.rb
Expand Up @@ -31,6 +31,31 @@ def config.array_serializer
# ref: http://jsonapi.org/format/#document-top-level
config.jsonapi_include_toplevel_object = false

# example output
# => [
# "::Api::V1::ResNamespace::ResourceSerializer",
# "::Api::ResNamespace::ResourceSerializer",
# "::ResNamespace::ResourceSerializer" ,
# "::ResourceSerializer"]
#
# NOTE: lookup_namespace is often the ControllerClass.name
config.serializer_lookup_chain = ActiveModelSerializers::LookupChain::DEFAULT.dup
# config.serializer_lookup_chain = proc { |lookup_namespace, _, _|
# lookups = []
# current_resource = lookup_namespace.name.remove(/Controller\z/)
# current_resource += 'Serializer'
# namespaces = current_resource.split('::')
# resource_serializer = namespaces.slice!(-1)
#
# lookups << '::' + resource_serializer
# namespaces.length.times do |i|
# current_namespace = namespaces[i - namespaces.length..-1].join('::')
# lookups << '::' + current_namespace + '::' + resource_serializer
# end
#
# lookups
# }

config.schema_path = 'test/support/schemas'
end
end
Expand Down
1 change: 1 addition & 0 deletions lib/active_model_serializers.rb
Expand Up @@ -14,6 +14,7 @@ module ActiveModelSerializers
autoload :Adapter
autoload :JsonPointer
autoload :Deprecate
autoload :LookupChain

class << self; attr_accessor :logger; end
self.logger = ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(STDOUT))
Expand Down
70 changes: 70 additions & 0 deletions lib/active_model_serializers/lookup_chain.rb
@@ -0,0 +1,70 @@
module ActiveModelSerializers
module LookupChain
# Standard appending of Serializer to the resource name.
#
# Example:
# Author => AuthorSerializer
BY_RESOURCE = lambda do |resource_class, _serializer_class|
serializer_from(resource_class)
end

# Uses the namespace of the resource to find the serializer=
#
# Example:
# British::Author => British::AuthorSerializer
BY_NAMESPACE = lambda do |resource_class, _serializer_class|
resource_namespace = namespace_for(resource_class)
serializer_name = serializer_from(resource_class)

"#{resource_namespace}::#{serializer_name}"
end

# Allows for serializers to be defined in parent serializers
# - useful if a relationship only needs a different set of attributes
# than if it were rendered independently.
#
# Example:
# class BlogSerializer < ActiveModel::Serializer
# class AuthorSerialier < ActiveModel::Serializer
# ...
# end
#
# belongs_to :author
# ...
# end
#
# The belongs_to relationship would be rendered with
# BlogSerializer::AuthorSerialier
BY_PARENT_SERIALIZER = lambda do |resource_class, serializer_class|
return if serializer_class == ActiveModel::Serializer

serializer_name = serializer_from(resource_class)
"#{serializer_class.name}::#{serializer_name}"
end

DEFAULT = [
BY_PARENT_SERIALIZER,
BY_NAMESPACE,
BY_RESOURCE
].freeze

module_function

def namespace_for(klass)
klass.name.deconstantize
end

def resource_class_name(klass)
klass.name.demodulize
end

def serializer_from_resource_name(name)
"#{name}Serializer"
end

def serializer_from(klass)
name = resource_class_name(klass)
serializer_from_resource_name(name)
end
end
end
Empty file.
@@ -0,0 +1,42 @@
require 'test_helper'

describe 'feature' do
describe 'configuration' do
describe 'serializer lookup' do
describe 'using SerializableResource' do
it 'uses the child serializer' do
class Parent < ::Model; end
class Child < ::Model; end

class ParentSerializer < ActiveModel::Serializer
class ChildSerializer < ActiveModel::Serializer
attributes :name, :child_attr
def child_attr
true
end
end

attributes :name
belongs_to :child
end

parent = Parent.new(name: 'parent', child: Child.new(name: 'child'))
resource = ActiveModelSerializers::SerializableResource.new(
parent,
adapter: :attributes
)

expected = {
name: 'parent',
child: {
name: 'child',
child_attr: true
}
}

assert_equal expected, resource.serializable_hash
end
end
end
end
end

0 comments on commit ae3c820

Please sign in to comment.