Skip to content

Commit

Permalink
Move all associations related code to Associations module
Browse files Browse the repository at this point in the history
  • Loading branch information
Артём Большаков committed Jul 6, 2015
1 parent eddf4e7 commit 0768d04
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 101 deletions.
103 changes: 2 additions & 101 deletions lib/active_model/serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,13 @@ class Serializer
autoload :Configuration
autoload :ArraySerializer
autoload :Adapter
autoload :Association
autoload :Reflection
autoload :SingularReflection
autoload :CollectionReflection
autoload :BelongsToReflection
autoload :HasOneReflection
autoload :HasManyReflection

autoload :Associations
include Configuration
include Associations

class << self
attr_accessor :_attributes
attr_accessor :_attributes_keys
attr_accessor :_reflections
attr_accessor :_urls
attr_accessor :_cache
attr_accessor :_fragmented
Expand Down Expand Up @@ -74,57 +67,6 @@ def self.cache(options = {})
@_cache_options = (options.empty?) ? nil : options
end

# Defines an association in the object should be rendered.
#
# The serializer object should implement the association name
# as a method which should return an array when invoked. If a method
# with the association name does not exist, the association name is
# dispatched to the serialized object.
def self.has_many(*attrs)
associate attrs do |name, options|
HasManyReflection.new(name, options)
end
end

# Defines an association in the object that should be rendered.
#
# The serializer object should implement the association name
# as a method which should return an object when invoked. If a method
# with the association name does not exist, the association name is
# dispatched to the serialized object.
def self.belongs_to(*attrs)
associate attrs do |name, options|
BelongsToReflection.new(name, options)
end
end

# Defines an association in the object should be rendered.
#
# The serializer object should implement the association name
# as a method which should return an object when invoked. If a method
# with the association name does not exist, the association name is
# dispatched to the serialized object.
def self.has_one(*attrs)
associate attrs do |name, options|
HasOneReflection.new(name, options)
end
end

def self.associate(attrs, &block) #:nodoc:
options = attrs.extract_options!
self._reflections = _reflections.dup

attrs.each do |name|
unless method_defined?(name)
define_method name do
object.send name
end
end

self._reflections << block.call(name, options)
end
end

def self.url(attr)
@_urls.push attr
end
Expand Down Expand Up @@ -211,51 +153,10 @@ def attributes(options = {})
end
end


def associations
return unless object

Enumerator.new do |y|
self.class._reflections.dup.each do |reflection|
name = reflection.name
association_value = send(name)
reflection_options = reflection.options.dup
serializer_class = ActiveModel::Serializer.serializer_for(association_value, reflection_options)

if serializer_class
begin
serializer = serializer_class.new(
association_value,
serializer_options(reflection_options)
)
rescue ActiveModel::Serializer::ArraySerializer::NoSerializerError
virtual_value = association_value
virtual_value = virtual_value.as_json if virtual_value.respond_to?(:as_json)
reflection_options[:virtual_value] = virtual_value
end
elsif !association_value.nil? && !association_value.instance_of?(Object)
reflection_options[:virtual_value] = association_value
end

y.yield Association.new(name, serializer, reflection_options)
end
end
end

def self.serializers_cache
@serializers_cache ||= ThreadSafe::Cache.new
end

private

def serializer_options(reflection_options)
serializer = reflection_options.fetch(:serializer, nil)

serializer_options = options.except(:serializer)
serializer_options[:serializer] = serializer if serializer
serializer_options
end

attr_reader :options

def self.get_serializer_for(klass)
Expand Down
121 changes: 121 additions & 0 deletions lib/active_model/serializer/associations.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
module ActiveModel
class Serializer
module Associations
extend ActiveSupport::Concern

included do |base|
class << base
attr_accessor :_reflections
end

autoload :Association
autoload :Reflection
autoload :SingularReflection
autoload :CollectionReflection
autoload :BelongsToReflection
autoload :HasOneReflection
autoload :HasManyReflection
end

module ClassMethods
def self.inherited(base)
base._reflections = self._reflections.try(:dup) || []
super
end

# Defines an association in the object should be rendered.
#
# The serializer object should implement the association name
# as a method which should return an array when invoked. If a method
# with the association name does not exist, the association name is
# dispatched to the serialized object.
def has_many(*attrs)
associate attrs do |name, options|
HasManyReflection.new(name, options)
end
end

# Defines an association in the object that should be rendered.
#
# The serializer object should implement the association name
# as a method which should return an object when invoked. If a method
# with the association name does not exist, the association name is
# dispatched to the serialized object.
def belongs_to(*attrs)
associate attrs do |name, options|
BelongsToReflection.new(name, options)
end
end

# Defines an association in the object should be rendered.
#
# The serializer object should implement the association name
# as a method which should return an object when invoked. If a method
# with the association name does not exist, the association name is
# dispatched to the serialized object.
def has_one(*attrs)
associate attrs do |name, options|
HasOneReflection.new(name, options)
end
end

private

def associate(attrs, &block) #:nodoc:
options = attrs.extract_options!
self._reflections = _reflections.dup

attrs.each do |name|
unless method_defined?(name)
define_method name do
object.send name
end
end

self._reflections << block.call(name, options)
end
end
end

def associations
return unless object

Enumerator.new do |y|
self.class._reflections.dup.each do |reflection|
name = reflection.name
association_value = send(name)
reflection_options = reflection.options.dup
serializer_class = ActiveModel::Serializer.serializer_for(association_value, reflection_options)

if serializer_class
begin
serializer = serializer_class.new(
association_value,
serializer_options(reflection_options)
)
rescue ActiveModel::Serializer::ArraySerializer::NoSerializerError
virtual_value = association_value
virtual_value = virtual_value.as_json if virtual_value.respond_to?(:as_json)
reflection_options[:virtual_value] = virtual_value
end
elsif !association_value.nil? && !association_value.instance_of?(Object)
reflection_options[:virtual_value] = association_value
end

y.yield Association.new(name, serializer, reflection_options)
end
end
end

private

def serializer_options(reflection_options)
serializer = reflection_options.fetch(:serializer, nil)

serializer_options = options.except(:serializer)
serializer_options[:serializer] = serializer if serializer
serializer_options
end
end
end
end

0 comments on commit 0768d04

Please sign in to comment.