Skip to content

Commit

Permalink
Fix #955
Browse files Browse the repository at this point in the history
  • Loading branch information
bf4 committed Jun 21, 2015
1 parent 728b939 commit 56a7bd1
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 10 deletions.
20 changes: 16 additions & 4 deletions lib/active_model/serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -222,10 +222,22 @@ def each_association(&block)
serializer_class = ActiveModel::Serializer.serializer_for(association_value, association_options)

if serializer_class
serializer = serializer_class.new(
association_value,
options.except(:serializer).merge(serializer_from_options(association_options))
)
begin
serializer = serializer_class.new(
association_value,
options.except(:serializer).merge(serializer_from_options(association_options))
)
rescue NoMethodError
# 1. Failure to serialize an element in a collection, e.g. [ {hi: "Steve" } ] will fail
# with NoMethodError when the ArraySerializer finds no serializer for the hash { hi: "Steve" },
# and tries to call new on that nil.
# 2. Convert association_value to hash using implicit as_json
# 3. Set as virtual value (serializer is nil)
# 4. Consider warning when this happens
virtual_value = association_value
virtual_value = virtual_value.as_json if virtual_value.respond_to?(:as_json)
association_options[:association_options][:virtual_value] = virtual_value
end
elsif !association_value.nil? && !association_value.instance_of?(Object)
association_options[:association_options][:virtual_value] = association_value
end
Expand Down
22 changes: 17 additions & 5 deletions test/adapter/json/has_many_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class HasManyTestTest < Minitest::Test
def setup
ActionController::Base.cache_store.clear
@author = Author.new(id: 1, name: 'Steve K.')
@post = Post.new(title: 'New Post', body: 'Body')
@post = Post.new(id: 42, title: 'New Post', body: 'Body')
@first_comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
@second_comment = Comment.new(id: 2, body: 'ZOMG ANOTHER COMMENT')
@post.comments = [@first_comment, @second_comment]
Expand All @@ -17,16 +17,28 @@ def setup
@second_comment.post = @post
@blog = Blog.new(id: 1, name: "My Blog!!")
@post.blog = @blog

@serializer = PostSerializer.new(@post)
@adapter = ActiveModel::Serializer::Adapter::Json.new(@serializer)
@tag = Tag.new(id: 1, name: "#hash_tag")
@post.tags = [@tag]
end

def test_has_many
serializer = PostSerializer.new(@post)
adapter = ActiveModel::Serializer::Adapter::Json.new(serializer)
assert_equal([
{id: 1, body: 'ZOMG A COMMENT'},
{id: 2, body: 'ZOMG ANOTHER COMMENT'}
], @adapter.serializable_hash[:post][:comments])
], adapter.serializable_hash[:post][:comments])
end

def test_has_many_with_no_serializer
serializer = PostWithTagsSerializer.new(@post)
adapter = ActiveModel::Serializer::Adapter::Json.new(serializer)
assert_equal({
id: 42,
tags: [
{"attributes"=>{"id"=>1, "name"=>"#hash_tag"}}
]
}, adapter.serializable_hash[:post_with_tags])
end
end
end
Expand Down
17 changes: 16 additions & 1 deletion test/adapter/json_api/has_many_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ def setup
@blog.articles = [@post]
@post.blog = @blog
@post_without_comments.blog = nil

@tag = Tag.new(id: 1, name: "#hash_tag")
@post.tags = [@tag]
@serializer = PostSerializer.new(@post)
@adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer)
end
Expand Down Expand Up @@ -103,6 +104,20 @@ def test_include_type_for_association_when_different_than_name
}
assert_equal expected, actual
end

def test_has_many_with_no_serializer
serializer = PostWithTagsSerializer.new(@post)
adapter = ActiveModel::Serializer::Adapter::JsonApi.new(serializer)
assert_equal({
data: {
id: "1",
type: "posts",
relationships: {
tags: {:data=>nil}
}
}
}, adapter.serializable_hash)
end
end
end
end
Expand Down
7 changes: 7 additions & 0 deletions test/fixtures/poro.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ class ProfilePreviewSerializer < ActiveModel::Serializer
User = Class.new(Model)
Location = Class.new(Model)
Place = Class.new(Model)
Tag = Class.new(Model)

module Spam; end
Spam::UnrelatedLink = Class.new(Model)
Expand Down Expand Up @@ -219,6 +220,12 @@ def self.root_name
belongs_to :author, serializer: AuthorPreviewSerializer
end

PostWithTagsSerializer = Class.new(ActiveModel::Serializer) do
attributes :id

has_many :tags
end

Spam::UnrelatedLinkSerializer = Class.new(ActiveModel::Serializer) do
attributes :id
end
Expand Down
10 changes: 10 additions & 0 deletions test/serializers/associations_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ def setup
@author.roles = []
@blog = Blog.new({ name: 'AMS Blog' })
@post = Post.new({ title: 'New Post', body: 'Body' })
@tag = Tag.new({name: '#hashtagged'})
@comment = Comment.new({ id: 1, body: 'ZOMG A COMMENT' })
@post.comments = [@comment]
@post.tags = [@tag]
@post.blog = @blog
@comment.post = @post
@comment.author = nil
Expand Down Expand Up @@ -65,6 +67,14 @@ def test_has_many_and_has_one
end
end

def test_has_many_with_no_serializer
PostWithTagsSerializer.new(@post).each_association do |name, serializer, options|
assert_equal name, :tags
assert_equal serializer, nil
assert_equal options, {:virtual_value=>[{"attributes"=>{"name"=>"#hashtagged"}}]}
end
end

def test_serializer_options_are_passed_into_associations_serializers
@post_serializer.each_association do |name, association|
if name == :comments
Expand Down

0 comments on commit 56a7bd1

Please sign in to comment.