Skip to content

Commit cf77786

Browse files
bf4joaomdmoura
authored andcommitted
Fix #955
1 parent 3710c32 commit cf77786

File tree

4 files changed

+40
-13
lines changed

4 files changed

+40
-13
lines changed

lib/active_model/serializer.rb

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -206,10 +206,22 @@ def each_association(&block)
206206
serializer_class = ActiveModel::Serializer.serializer_for(association_value, association_options)
207207

208208
if serializer_class
209-
serializer = serializer_class.new(
210-
association_value,
211-
options.except(:serializer).merge(serializer_from_options(association_options))
212-
)
209+
begin
210+
serializer = serializer_class.new(
211+
association_value,
212+
options.except(:serializer).merge(serializer_from_options(association_options))
213+
)
214+
rescue NoMethodError
215+
# 1. Failure to serialize an element in a collection, e.g. [ {hi: "Steve" } ] will fail
216+
# with NoMethodError when the ArraySerializer finds no serializer for the hash { hi: "Steve" },
217+
# and tries to call new on that nil.
218+
# 2. Convert association_value to hash using implicit as_json
219+
# 3. Set as virtual value (serializer is nil)
220+
# 4. Consider warning when this happens
221+
virtual_value = association_value
222+
virtual_value = virtual_value.as_json if virtual_value.respond_to?(:as_json)
223+
association_options[:association_options][:virtual_value] = virtual_value
224+
end
213225
elsif !association_value.nil? && !association_value.instance_of?(Object)
214226
association_options[:association_options][:virtual_value] = association_value
215227
end

test/adapter/json/has_many_test.rb

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class HasManyTestTest < Minitest::Test
88
def setup
99
ActionController::Base.cache_store.clear
1010
@author = Author.new(id: 1, name: 'Steve K.')
11-
@post = Post.new(title: 'New Post', body: 'Body')
11+
@post = Post.new(id: 42, title: 'New Post', body: 'Body')
1212
@first_comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
1313
@second_comment = Comment.new(id: 2, body: 'ZOMG ANOTHER COMMENT')
1414
@post.comments = [@first_comment, @second_comment]
@@ -19,22 +19,26 @@ def setup
1919
@post.blog = @blog
2020
@tag = Tag.new(id: 1, name: "#hash_tag")
2121
@post.tags = [@tag]
22-
23-
@serializer = PostSerializer.new(@post)
24-
@adapter = ActiveModel::Serializer::Adapter::Json.new(@serializer)
2522
end
2623

2724
def test_has_many
25+
serializer = PostSerializer.new(@post)
26+
adapter = ActiveModel::Serializer::Adapter::Json.new(serializer)
2827
assert_equal([
2928
{id: 1, body: 'ZOMG A COMMENT'},
3029
{id: 2, body: 'ZOMG ANOTHER COMMENT'}
31-
], @adapter.serializable_hash[:post][:comments])
30+
], adapter.serializable_hash[:post][:comments])
3231
end
3332

3433
def test_has_many_with_no_serializer
3534
serializer = PostWithTagsSerializer.new(@post)
3635
adapter = ActiveModel::Serializer::Adapter::Json.new(serializer)
37-
assert_includes(adapter.as_json, :tags)
36+
assert_equal({
37+
id: 42,
38+
tags: [
39+
{"attributes"=>{"id"=>1, "name"=>"#hash_tag"}}
40+
]
41+
}, adapter.serializable_hash[:post_with_tags])
3842
end
3943
end
4044
end

test/adapter/json_api/has_many_test.rb

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ def setup
2929
@post_without_comments.blog = nil
3030
@tag = Tag.new(id: 1, name: "#hash_tag")
3131
@post.tags = [@tag]
32-
3332
@serializer = PostSerializer.new(@post)
3433
@adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer)
3534
end
@@ -97,6 +96,7 @@ def test_include_type_for_association_when_different_than_name
9796
serializer = BlogSerializer.new(@blog)
9897
adapter = ActiveModel::Serializer::Adapter::JsonApi.new(serializer)
9998
actual = adapter.serializable_hash[:data][:relationships][:articles]
99+
100100
expected = {
101101
data: [{
102102
type: "posts",
@@ -109,7 +109,16 @@ def test_include_type_for_association_when_different_than_name
109109
def test_has_many_with_no_serializer
110110
serializer = PostWithTagsSerializer.new(@post)
111111
adapter = ActiveModel::Serializer::Adapter::JsonApi.new(serializer)
112-
assert_includes(adapter.serializable_hash, :tags)
112+
113+
assert_equal({
114+
data: {
115+
id: "1",
116+
type: "posts",
117+
relationships: {
118+
tags: {:data=>nil}
119+
}
120+
}
121+
}, adapter.serializable_hash)
113122
end
114123
end
115124
end

test/serializers/associations_test.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ def test_has_many_and_has_one
6969

7070
def test_has_many_with_no_serializer
7171
PostWithTagsSerializer.new(@post).each_association do |name, serializer, options|
72-
puts "The line above will crash this test"
72+
assert_equal name, :tags
73+
assert_equal serializer, nil
74+
assert_equal options, {:virtual_value=>[{"attributes"=>{"name"=>"#hashtagged"}}]}
7375
end
7476
end
7577

0 commit comments

Comments
 (0)