-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move all associations related code to Associations module
- Loading branch information
Артём Большаков
committed
Jul 6, 2015
1 parent
eddf4e7
commit 0768d04
Showing
2 changed files
with
123 additions
and
101 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |