Skip to content

Commit

Permalink
--wip--
Browse files Browse the repository at this point in the history
  • Loading branch information
Артём Большаков committed Jul 6, 2015
1 parent 4b75b34 commit 3c3ade1
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 25 deletions.
63 changes: 46 additions & 17 deletions lib/active_model/serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ class << self
end

def self.inherited(base)
base._attributes = self._attributes.try(:dup) || []
base._attributes = self._attributes.try(:dup) || []
base._attributes_keys = self._attributes_keys.try(:dup) || {}
base._associations = self._associations.try(:dup) || {}
base._associations = self._associations.try(:dup) || []
base._urls = []
serializer_file = File.open(caller.first[/^[^:]+/])
base._cache_digest = Digest::MD5.hexdigest(serializer_file.read)
Expand All @@ -45,7 +45,7 @@ def self.attributes(*attrs)

def self.attribute(attr, options = {})
key = options.fetch(:key, attr)
@_attributes_keys[attr] = {key: key} if key != attr
@_attributes_keys[attr] = { key: key } if key != attr
@_attributes << key unless @_attributes.include?(key)
define_method key do
object.read_attribute_for_serialization(attr)
Expand All @@ -58,21 +58,27 @@ def self.fragmented(serializer)

# Enables a serializer to be automatically cached
def self.cache(options = {})
@_cache = ActionController::Base.cache_store if Rails.configuration.action_controller.perform_caching
@_cache_key = options.delete(:key)
@_cache_only = options.delete(:only)
@_cache_except = options.delete(:except)
@_cache = ActionController::Base.cache_store if Rails.configuration.action_controller.perform_caching
@_cache_key = options.delete(:key)
@_cache_only = options.delete(:only)
@_cache_except = options.delete(:except)
@_cache_options = (options.empty?) ? nil : options
end

Association = Struct.new(:name, :options)
SingularAssociation = Class.new(Association)
CollectionAssociation = Class.new(Association)

# 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(:has_many, attrs)
associate attrs do |name, options|
CollectionAssociation.new(name, options)
end
end

# Defines an association in the object that should be rendered.
Expand All @@ -82,7 +88,9 @@ def self.has_many(*attrs)
# with the association name does not exist, the association name is
# dispatched to the serialized object.
def self.belongs_to(*attrs)
associate(:belongs_to, attrs)
associate attrs do |name, options|
SingularAssociation.new(name, options)
end
end

# Defines an association in the object should be rendered.
Expand All @@ -92,21 +100,24 @@ def self.belongs_to(*attrs)
# with the association name does not exist, the association name is
# dispatched to the serialized object.
def self.has_one(*attrs)
associate(:has_one, attrs)
associate attrs do |name, options|
SingularAssociation.new(name, options)
end
end

def self.associate(type, attrs) #:nodoc:
# has_one :author, :image, only: :object
def self.associate(attrs, &block) #:nodoc:
options = attrs.extract_options!
self._associations = _associations.dup

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

self._associations[attr] = {type: type, association_options: options}
self._associations << block.call(name, options)
end
end

Expand Down Expand Up @@ -198,11 +209,29 @@ def attributes(options = {})
end
end

def associations
Enumerator.new do |y|
self.class._associations.dup.each do |association|
y.yield association
end
end
end

# @return [Enumerable]
#
def associations

end
require 'pp'
def each_association(&block)
return unless object
return unless block_given?

self.class._associations.dup.each do |name, association_options|
# self._associations[attr] = {type: type, association_options: options}
self.class._associations.dup.each do |association|
name = association.name
association_options = association.options

association_value = send(name)

serializer_class = ActiveModel::Serializer.serializer_for(association_value, association_options)
Expand Down
18 changes: 10 additions & 8 deletions test/serializers/associations_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def setup
@post.author = @author
@author.posts = [@post]

@post_serializer = PostSerializer.new(@post, {custom_options: true})
@post_serializer = PostSerializer.new(@post, {custom_options: true})
@author_serializer = AuthorSerializer.new(@author)
@comment_serializer = CommentSerializer.new(@comment)
Expand Down Expand Up @@ -122,15 +123,16 @@ def test_associations_inheritance_with_new_association
inherited_klass = Class.new(PostSerializer) do
has_many :top_comments, serializer: CommentSerializer
end
expected_associations = PostSerializer._associations.merge(
top_comments: {
type: :has_many,
association_options: {
serializer: CommentSerializer
}
}

inherited_associations = inherited_klass._associations
parent_associations = PostSerializer._associations

assert(
parent_associations.all? do |association|
inherited_associations.include?(association)
end
)
assert_equal(inherited_klass._associations, expected_associations)
assert(inherited_associations.map(&:name).include?(:top_comments))
end
end
end
Expand Down

0 comments on commit 3c3ade1

Please sign in to comment.