Skip to content

Commit 33c0300

Browse files
committed
Update Json, FlattenJson adapters.
1 parent 0e43a6e commit 33c0300

File tree

5 files changed

+91
-107
lines changed

5 files changed

+91
-107
lines changed

lib/active_model/serializer/adapter.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ class Adapter
66
extend ActiveSupport::Autoload
77
autoload :Json
88
autoload :FlattenJson
9-
autoload :NestedJson
109
autoload :Null
1110
autoload :JsonApi
1211

lib/active_model/serializer/adapter/flatten_json.rb

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,17 @@ module ActiveModel
22
class Serializer
33
class Adapter
44
class FlattenJson < Json
5-
def serializable_hash(options = {})
6-
super
7-
@result
8-
end
9-
105
private
116

12-
# no-op: FlattenJson adapter does not include meta data, because it does not support root.
7+
def rooting?
8+
false
9+
end
10+
1311
def include_meta(json)
1412
json
1513
end
1614
end
1715
end
1816
end
1917
end
18+

lib/active_model/serializer/adapter/json.rb

Lines changed: 68 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4,49 +4,84 @@ module ActiveModel
44
class Serializer
55
class Adapter
66
class Json < Adapter
7-
def serializable_hash(options = nil)
7+
cattr_accessor :default_limit_depth, :default_check_depth_strategy
8+
self.default_limit_depth = 1
9+
self.default_check_depth_strategy = :trim
10+
11+
def serializable_hash options = nil
812
options ||= {}
9-
if serializer.respond_to?(:each)
10-
@result = serializer.map { |s| FlattenJson.new(s).serializable_hash(options) }
11-
else
12-
@hash = {}
13+
@current_depth = options[:_current_depth] || 0
14+
@without_root = options[:_without_root]
15+
@limit_depth = options[:limit_depth] || default_limit_depth
16+
@check_depth_strategy = options[:check_depth_strategy] || default_check_depth_strategy
1317

14-
@core = cache_check(serializer) do
15-
serializer.attributes(options)
16-
end
18+
@result =
19+
serialize_collection(serializer, options.merge(_without_root: true)) ||
20+
serialize_attributes(options).merge(serialize_associations)
21+
rooting? ? { root => @result } : @result
22+
end
23+
24+
def fragment_cache(cached_hash, non_cached_hash)
25+
Json::FragmentCache.new().fragment_cache(cached_hash, non_cached_hash)
26+
end
27+
28+
private
29+
30+
def rooting?
31+
!@without_root && (@current_depth == 0)
32+
end
33+
34+
def serialize_object serializer, options = {}
35+
if serializer.try(:object)
36+
self.class.new(serializer).serializable_hash(options)
37+
end
38+
end
1739

40+
def serialize_collection serializers, options = {}
41+
if serializers.respond_to?(:each)
42+
serializers.map { |s| serialize_object(s, options) }
43+
end
44+
end
45+
46+
def serialize_attributes options
47+
cache_check(serializer) do
48+
serializer.attributes(options)
49+
end
50+
end
51+
52+
def serialize_associations
53+
hash = {}
54+
next_depth = @current_depth + 1
55+
cascading_options = {
56+
limit_depth: @limit_depth,
57+
check_depth_strategy: @check_depth_strategy,
58+
_current_depth: next_depth
59+
}
60+
unless too_deep? next_depth
1861
serializer.associations.each do |association|
1962
serializer = association.serializer
20-
opts = association.options
21-
22-
if serializer.respond_to?(:each)
23-
array_serializer = serializer
24-
@hash[association.key] = array_serializer.map do |item|
25-
cache_check(item) do
26-
item.attributes(opts)
27-
end
28-
end
29-
else
30-
@hash[association.key] =
31-
if serializer && serializer.object
32-
cache_check(serializer) do
33-
serializer.attributes(options)
34-
end
35-
elsif opts[:virtual_value]
36-
opts[:virtual_value]
37-
end
38-
end
63+
opts = association.options.merge(cascading_options)
64+
hash[association.key] =
65+
serialize_collection(serializer, opts) ||
66+
serialize_object(serializer, opts) ||
67+
opts[:virtual_value]
3968
end
40-
@result = @core.merge @hash
4169
end
42-
43-
{ root => @result }
70+
hash
4471
end
4572

46-
def fragment_cache(cached_hash, non_cached_hash)
47-
Json::FragmentCache.new().fragment_cache(cached_hash, non_cached_hash)
73+
def too_deep? depth
74+
if depth > @limit_depth
75+
case @check_depth_strategy
76+
when :fail
77+
fail 'Too deep associations.'
78+
when :trim
79+
true
80+
end
81+
else
82+
false
83+
end
4884
end
49-
5085
end
5186
end
5287
end

lib/active_model/serializer/adapter/nested_json.rb

Lines changed: 0 additions & 63 deletions
This file was deleted.

test/adapter/nested_json_test.rb renamed to test/adapter/json/nested_json_test.rb

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def setup
1414
@author.posts = [@post]
1515

1616
@serializer = AuthorNestedSerializer.new(@author)
17-
@adapter = ActiveModel::Serializer::Adapter::NestedJson.new(@serializer)
17+
@adapter = ActiveModel::Serializer::Adapter::Json.new(@serializer)
1818
end
1919

2020
def test_has_many
@@ -27,14 +27,28 @@ def test_has_many
2727
{id: 2, body: 'ZOMG ANOTHER COMMENT'}
2828
]
2929
}]
30-
}, @adapter.serializable_hash)
30+
}, @adapter.serializable_hash(limit_depth: 5)[:author])
3131
end
3232

3333
def test_limit_depth
34-
assert_raises do
35-
@adapter.serializable_hash(limit_depth: 1)
34+
assert_raises(StandardError) do
35+
@adapter.serializable_hash(limit_depth: 1, check_depth_strategy: :fail)
3636
end
3737
end
38+
39+
def test_flatten_json
40+
adapter = ActiveModel::Serializer::Adapter::FlattenJson.new(@serializer)
41+
assert_equal({
42+
id: 1, name: 'Steve K.',
43+
posts: [{
44+
id: 1, title: 'New Post', body: 'Body',
45+
comments: [
46+
{id: 1, body: 'ZOMG A COMMENT'},
47+
{id: 2, body: 'ZOMG ANOTHER COMMENT'}
48+
]
49+
}]
50+
}, adapter.serializable_hash(limit_depth: 5))
51+
end
3852
end
3953
end
4054
end

0 commit comments

Comments
 (0)