simplified the API for include_associations!() to make conditional includes cleaner

This commit is contained in:
Dan Gebhardt 2012-08-29 07:42:23 -04:00
parent 001c1d0634
commit 68dc57eb73
2 changed files with 65 additions and 31 deletions

View File

@ -460,8 +460,7 @@ module ActiveModel
# Returns a json representation of the serializable # Returns a json representation of the serializable
# object including the root. # object including the root.
def as_json(options=nil) def as_json(options={})
options ||= {}
if root = options.fetch(:root, @options.fetch(:root, _root)) if root = options.fetch(:root, @options.fetch(:root, _root))
@options[:hash] = hash = {} @options[:hash] = hash = {}
@options[:unique_values] = {} @options[:unique_values] = {}
@ -477,33 +476,17 @@ module ActiveModel
# object without the root. # object without the root.
def serializable_hash def serializable_hash
instrument(:serialize, :serializer => self.class.name) do instrument(:serialize, :serializer => self.class.name) do
node = attributes @node = attributes
instrument :associations do instrument :associations do
include_associations!(node) if _embed include_associations! if _embed
end end
node @node
end end
end end
def include_associations!(node) def include_associations!
_associations.each do |attr, klass| _associations.each_key do |name|
opts = { :node => node } include! name
if options.include?(:include) || options.include?(:exclude)
opts[:include] = included_association?(attr)
end
include! attr, opts
end
end
def included_association?(name)
if options.key?(:include)
options[:include].include?(name)
elsif options.key?(:exclude)
!options[:exclude].include?(name)
else
true
end end
end end
@ -526,9 +509,17 @@ module ActiveModel
@options[:unique_values] ||= {} @options[:unique_values] ||= {}
end end
node = options[:node] node = options[:node] ||= @node
value = options[:value] value = options[:value]
if options[:include] == nil
if @options.key?(:include)
options[:include] = @options[:include].include?(name)
elsif @options.include?(:exclude)
options[:include] = !@options[:exclude].include?(name)
end
end
association_class = association_class =
if klass = _associations[name] if klass = _associations[name]
klass klass

View File

@ -37,10 +37,11 @@ class SerializerTest < ActiveModel::TestCase
def initialize(attributes) def initialize(attributes)
super(attributes) super(attributes)
self.comments ||= [] self.comments ||= []
self.comments_disabled = false
self.author = nil self.author = nil
end end
attr_accessor :comments, :author attr_accessor :comments, :comments_disabled, :author
def active_model_serializer; PostSerializer; end def active_model_serializer; PostSerializer; end
end end
@ -89,11 +90,6 @@ class SerializerTest < ActiveModel::TestCase
end end
end end
class PostSerializer < ActiveModel::Serializer
attributes :title, :body
has_many :comments, :serializer => CommentSerializer
end
def test_scope_works_correct def test_scope_works_correct
serializer = ActiveModel::Serializer.new :foo, :scope => :bar serializer = ActiveModel::Serializer.new :foo, :scope => :bar
assert_equal serializer.scope, :bar assert_equal serializer.scope, :bar
@ -163,6 +159,11 @@ class SerializerTest < ActiveModel::TestCase
}, hash) }, hash)
end end
class PostSerializer < ActiveModel::Serializer
attributes :title, :body
has_many :comments, :serializer => CommentSerializer
end
def test_has_many def test_has_many
user = User.new user = User.new
@ -184,6 +185,48 @@ class SerializerTest < ActiveModel::TestCase
}, post_serializer.as_json) }, post_serializer.as_json)
end end
class PostWithConditionalCommentsSerializer < ActiveModel::Serializer
root :post
attributes :title, :body
has_many :comments, :serializer => CommentSerializer
def include_associations!
include! :comments unless object.comments_disabled
end
end
def test_conditionally_included_associations
user = User.new
post = Post.new(:title => "New Post", :body => "Body of new post", :email => "tenderlove@tenderlove.com")
comments = [Comment.new(:title => "Comment1"), Comment.new(:title => "Comment2")]
post.comments = comments
post_serializer = PostWithConditionalCommentsSerializer.new(post, :scope => user)
# comments enabled
post.comments_disabled = false
assert_equal({
:post => {
:title => "New Post",
:body => "Body of new post",
:comments => [
{ :title => "Comment1" },
{ :title => "Comment2" }
]
}
}, post_serializer.as_json)
# comments disabled
post.comments_disabled = true
assert_equal({
:post => {
:title => "New Post",
:body => "Body of new post"
}
}, post_serializer.as_json)
end
class Blog < Model class Blog < Model
attr_accessor :author attr_accessor :author
end end