active_model_serializers 0.10.0.rc1 → 0.10.0.rc2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +1 -2
- data/Gemfile +1 -1
- data/README.md +6 -3
- data/lib/action_controller/serialization.rb +9 -1
- data/lib/active_model/serializer.rb +15 -21
- data/lib/active_model/serializer/adapter.rb +13 -4
- data/lib/active_model/serializer/adapter/flatten_json.rb +12 -0
- data/lib/active_model/serializer/adapter/fragment_cache.rb +5 -5
- data/lib/active_model/serializer/adapter/json.rb +8 -10
- data/lib/active_model/serializer/adapter/json_api.rb +34 -30
- data/lib/active_model/serializer/adapter/json_api/fragment_cache.rb +3 -2
- data/lib/active_model/serializer/array_serializer.rb +8 -5
- data/lib/active_model/serializer/configuration.rb +1 -1
- data/lib/active_model/serializer/fieldset.rb +2 -2
- data/lib/active_model/serializer/railtie.rb +8 -0
- data/lib/active_model/serializer/version.rb +1 -1
- data/lib/active_model_serializers.rb +1 -0
- data/lib/generators/serializer/resource_override.rb +12 -0
- data/test/action_controller/adapter_selector_test.rb +7 -5
- data/test/action_controller/explicit_serializer_test.rb +33 -9
- data/test/action_controller/json_api_linked_test.rb +25 -19
- data/test/action_controller/rescue_from_test.rb +32 -0
- data/test/action_controller/serialization_scope_name_test.rb +2 -2
- data/test/action_controller/serialization_test.rb +41 -23
- data/test/adapter/fragment_cache_test.rb +1 -1
- data/test/adapter/json/belongs_to_test.rb +9 -2
- data/test/adapter/json/collection_test.rb +16 -2
- data/test/adapter/json/has_many_test.rb +1 -1
- data/test/adapter/json_api/belongs_to_test.rb +45 -35
- data/test/adapter/json_api/collection_test.rb +30 -23
- data/test/adapter/json_api/has_many_embed_ids_test.rb +2 -2
- data/test/adapter/json_api/has_many_explicit_serializer_test.rb +14 -14
- data/test/adapter/json_api/has_many_test.rb +22 -18
- data/test/adapter/json_api/has_one_test.rb +8 -6
- data/test/adapter/json_api/linked_test.rb +97 -71
- data/test/adapter/json_test.rb +1 -1
- data/test/adapter_test.rb +1 -1
- data/test/array_serializer_test.rb +14 -0
- data/test/fixtures/poro.rb +31 -7
- data/test/generators/scaffold_controller_generator_test.rb +24 -0
- data/test/{serializers/generators_test.rb → generators/serializer_generator_test.rb} +2 -10
- data/test/serializers/adapter_for_test.rb +1 -1
- data/test/serializers/associations_test.rb +21 -0
- data/test/serializers/attribute_test.rb +16 -1
- data/test/serializers/attributes_test.rb +35 -0
- data/test/serializers/cache_test.rb +14 -4
- data/test/serializers/configuration_test.rb +1 -1
- data/test/serializers/meta_test.rb +38 -9
- data/test/serializers/serializer_for_test.rb +9 -0
- data/test/test_helper.rb +10 -7
- metadata +12 -5
@@ -10,9 +10,10 @@ module ActiveModel
|
|
10
10
|
core_non_cached = non_cached_hash.first
|
11
11
|
no_root_cache = cached_hash.delete_if {|key, value| key == core_cached[0] }
|
12
12
|
no_root_non_cache = non_cached_hash.delete_if {|key, value| key == core_non_cached[0] }
|
13
|
-
cached_resource = (core_cached[1]) ? core_cached[1].
|
13
|
+
cached_resource = (core_cached[1]) ? core_cached[1].deep_merge(core_non_cached[1]) : core_non_cached[1]
|
14
14
|
hash = (root) ? { root => cached_resource } : cached_resource
|
15
|
-
|
15
|
+
|
16
|
+
hash.deep_merge no_root_non_cache.deep_merge no_root_cache
|
16
17
|
end
|
17
18
|
|
18
19
|
end
|
@@ -7,21 +7,24 @@ module ActiveModel
|
|
7
7
|
attr_reader :meta, :meta_key
|
8
8
|
|
9
9
|
def initialize(objects, options = {})
|
10
|
-
|
11
|
-
|
12
|
-
@objects = objects.map do |object|
|
10
|
+
@resource = objects
|
11
|
+
@objects = objects.map do |object|
|
13
12
|
serializer_class = options.fetch(
|
14
13
|
:serializer,
|
15
14
|
ActiveModel::Serializer.serializer_for(object)
|
16
15
|
)
|
17
|
-
serializer_class.new(object, options)
|
16
|
+
serializer_class.new(object, options.except(:serializer))
|
18
17
|
end
|
19
18
|
@meta = options[:meta]
|
20
19
|
@meta_key = options[:meta_key]
|
21
20
|
end
|
22
21
|
|
23
22
|
def json_key
|
24
|
-
|
23
|
+
if @objects.first
|
24
|
+
@objects.first.json_key.pluralize
|
25
|
+
else
|
26
|
+
@resource.name.downcase.pluralize if @resource.try(:name)
|
27
|
+
end
|
25
28
|
end
|
26
29
|
|
27
30
|
def root=(root)
|
@@ -3,7 +3,7 @@ require 'test_helper'
|
|
3
3
|
module ActionController
|
4
4
|
module Serialization
|
5
5
|
class AdapterSelectorTest < ActionController::TestCase
|
6
|
-
class
|
6
|
+
class AdapterSelectorTestController < ActionController::Base
|
7
7
|
def render_using_default_adapter
|
8
8
|
@profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
|
9
9
|
render json: @profile
|
@@ -20,7 +20,7 @@ module ActionController
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
tests
|
23
|
+
tests AdapterSelectorTestController
|
24
24
|
|
25
25
|
def test_render_using_default_adapter
|
26
26
|
get :render_using_default_adapter
|
@@ -32,10 +32,12 @@ module ActionController
|
|
32
32
|
|
33
33
|
expected = {
|
34
34
|
data: {
|
35
|
-
name: "Name 1",
|
36
|
-
description: "Description 1",
|
37
35
|
id: assigns(:profile).id.to_s,
|
38
|
-
type: "profiles"
|
36
|
+
type: "profiles",
|
37
|
+
attributes: {
|
38
|
+
name: "Name 1",
|
39
|
+
description: "Description 1",
|
40
|
+
}
|
39
41
|
}
|
40
42
|
}
|
41
43
|
|
@@ -3,7 +3,7 @@ require 'test_helper'
|
|
3
3
|
module ActionController
|
4
4
|
module Serialization
|
5
5
|
class ExplicitSerializerTest < ActionController::TestCase
|
6
|
-
class
|
6
|
+
class ExplicitSerializerTestController < ActionController::Base
|
7
7
|
def render_using_explicit_serializer
|
8
8
|
@profile = Profile.new(name: 'Name 1',
|
9
9
|
description: 'Description 1',
|
@@ -55,9 +55,16 @@ module ActionController
|
|
55
55
|
|
56
56
|
render json: [@post], each_serializer: PostPreviewSerializer
|
57
57
|
end
|
58
|
+
|
59
|
+
def render_using_explicit_each_serializer
|
60
|
+
location = Location.new(id: 42, lat: '-23.550520', lng: '-46.633309')
|
61
|
+
place = Place.new(id: 1337, name: 'Amazing Place', locations: [location])
|
62
|
+
|
63
|
+
render json: place, each_serializer: PlaceSerializer
|
64
|
+
end
|
58
65
|
end
|
59
66
|
|
60
|
-
tests
|
67
|
+
tests ExplicitSerializerTestController
|
61
68
|
|
62
69
|
def test_render_using_explicit_serializer
|
63
70
|
get :render_using_explicit_serializer
|
@@ -70,17 +77,15 @@ module ActionController
|
|
70
77
|
get :render_array_using_explicit_serializer
|
71
78
|
assert_equal 'application/json', @response.content_type
|
72
79
|
|
73
|
-
expected =
|
74
|
-
'
|
75
|
-
|
76
|
-
|
77
|
-
]
|
78
|
-
}
|
80
|
+
expected = [
|
81
|
+
{ 'name' => 'Name 1' },
|
82
|
+
{ 'name' => 'Name 2' }
|
83
|
+
]
|
79
84
|
|
80
85
|
assert_equal expected.to_json, @response.body
|
81
86
|
end
|
82
87
|
|
83
|
-
def
|
88
|
+
def test_render_array_using_implicit_serializer
|
84
89
|
get :render_array_using_implicit_serializer
|
85
90
|
assert_equal 'application/json', @response.content_type
|
86
91
|
|
@@ -105,6 +110,25 @@ module ActionController
|
|
105
110
|
|
106
111
|
assert_equal expected.to_json, @response.body
|
107
112
|
end
|
113
|
+
|
114
|
+
def test_render_using_explicit_each_serializer
|
115
|
+
get :render_using_explicit_each_serializer
|
116
|
+
|
117
|
+
expected = {
|
118
|
+
id: 1337,
|
119
|
+
name: "Amazing Place",
|
120
|
+
locations: [
|
121
|
+
{
|
122
|
+
id: 42,
|
123
|
+
lat: "-23.550520",
|
124
|
+
lng: "-46.633309",
|
125
|
+
place: "Nowhere" # is a virtual attribute on LocationSerializer
|
126
|
+
}
|
127
|
+
]
|
128
|
+
}
|
129
|
+
|
130
|
+
assert_equal expected.to_json, response.body
|
131
|
+
end
|
108
132
|
end
|
109
133
|
end
|
110
134
|
end
|
@@ -3,7 +3,7 @@ require 'test_helper'
|
|
3
3
|
module ActionController
|
4
4
|
module Serialization
|
5
5
|
class JsonApiLinkedTest < ActionController::TestCase
|
6
|
-
class
|
6
|
+
class JsonApiLinkedTestController < ActionController::Base
|
7
7
|
def setup_post
|
8
8
|
ActionController::Base.cache_store.clear
|
9
9
|
@role1 = Role.new(id: 1, name: 'admin')
|
@@ -78,7 +78,7 @@ module ActionController
|
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
81
|
-
tests
|
81
|
+
tests JsonApiLinkedTestController
|
82
82
|
|
83
83
|
def test_render_resource_without_include
|
84
84
|
get :render_resource_without_include
|
@@ -91,7 +91,7 @@ module ActionController
|
|
91
91
|
response = JSON.parse(@response.body)
|
92
92
|
assert response.key? 'included'
|
93
93
|
assert_equal 1, response['included'].size
|
94
|
-
assert_equal 'Steve K.', response['included'].first['name']
|
94
|
+
assert_equal 'Steve K.', response['included'].first['attributes']['name']
|
95
95
|
end
|
96
96
|
|
97
97
|
def test_render_resource_with_nested_has_many_include
|
@@ -101,29 +101,35 @@ module ActionController
|
|
101
101
|
{
|
102
102
|
"id" => "1",
|
103
103
|
"type" => "authors",
|
104
|
-
"
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
"
|
104
|
+
"attributes" => {
|
105
|
+
"name" => "Steve K."
|
106
|
+
},
|
107
|
+
"relationships" => {
|
108
|
+
"posts" => { "data" => [] },
|
109
|
+
"roles" => { "data" => [{ "type" =>"roles", "id" => "1" }, { "type" =>"roles", "id" => "2" }] },
|
110
|
+
"bio" => { "data" => nil }
|
109
111
|
}
|
110
112
|
}, {
|
111
113
|
"id" => "1",
|
112
114
|
"type" => "roles",
|
113
|
-
"
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
115
|
+
"attributes" => {
|
116
|
+
"name" => "admin",
|
117
|
+
"description" => nil,
|
118
|
+
"slug" => "admin-1"
|
119
|
+
},
|
120
|
+
"relationships" => {
|
121
|
+
"author" => { "data" => { "type" =>"authors", "id" => "1" } }
|
118
122
|
}
|
119
123
|
}, {
|
120
124
|
"id" => "2",
|
121
125
|
"type" => "roles",
|
122
|
-
"
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
126
|
+
"attributes" => {
|
127
|
+
"name" => "colab",
|
128
|
+
"description" => nil,
|
129
|
+
"slug" => "colab-2"
|
130
|
+
},
|
131
|
+
"relationships" => {
|
132
|
+
"author" => { "data" => { "type" =>"authors", "id" => "1" } }
|
127
133
|
}
|
128
134
|
}
|
129
135
|
]
|
@@ -135,7 +141,7 @@ module ActionController
|
|
135
141
|
response = JSON.parse(@response.body)
|
136
142
|
assert response.key? 'included'
|
137
143
|
assert_equal 1, response['included'].size
|
138
|
-
assert_equal 'Anonymous', response['included'].first['name']
|
144
|
+
assert_equal 'Anonymous', response['included'].first['attributes']['name']
|
139
145
|
end
|
140
146
|
|
141
147
|
def test_render_collection_without_include
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module ActionController
|
4
|
+
module Serialization
|
5
|
+
class RescueFromTest < ActionController::TestCase
|
6
|
+
class RescueFromTestController < ActionController::Base
|
7
|
+
rescue_from Exception, with: :handle_error
|
8
|
+
|
9
|
+
def render_using_raise_error_serializer
|
10
|
+
@profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
|
11
|
+
render json: [@profile], serializer: RaiseErrorSerializer
|
12
|
+
end
|
13
|
+
|
14
|
+
def handle_error(exception)
|
15
|
+
render json: { errors: ['Internal Server Error'] }, status: :internal_server_error
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
tests RescueFromTestController
|
20
|
+
|
21
|
+
def test_rescue_from
|
22
|
+
get :render_using_raise_error_serializer
|
23
|
+
|
24
|
+
expected = {
|
25
|
+
errors: ['Internal Server Error']
|
26
|
+
}.to_json
|
27
|
+
|
28
|
+
assert_equal expected, @response.body
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -27,7 +27,7 @@ class DefaultScopeNameTest < ActionController::TestCase
|
|
27
27
|
|
28
28
|
def test_default_scope_name
|
29
29
|
get :render_new_user
|
30
|
-
assert_equal '{"data":{"
|
30
|
+
assert_equal '{"data":{"id":"1","type":"users","attributes":{"admin?":false}}}', @response.body
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
@@ -58,6 +58,6 @@ class SerializationScopeNameTest < ActionController::TestCase
|
|
58
58
|
|
59
59
|
def test_override_scope_name_with_controller
|
60
60
|
get :render_new_user
|
61
|
-
assert_equal '{"data":{"
|
61
|
+
assert_equal '{"data":{"id":"1","type":"users","attributes":{"admin?":true}}}', @response.body
|
62
62
|
end
|
63
63
|
end
|
@@ -3,15 +3,24 @@ require 'test_helper'
|
|
3
3
|
module ActionController
|
4
4
|
module Serialization
|
5
5
|
class ImplicitSerializerTest < ActionController::TestCase
|
6
|
-
class
|
6
|
+
class ImplicitSerializationTestController < ActionController::Base
|
7
7
|
def render_using_implicit_serializer
|
8
8
|
@profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
|
9
9
|
render json: @profile
|
10
10
|
end
|
11
11
|
|
12
12
|
def render_using_custom_root
|
13
|
-
|
14
|
-
|
13
|
+
with_adapter ActiveModel::Serializer::Adapter::Json do
|
14
|
+
@profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
|
15
|
+
render json: @profile, root: "custom_root"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def render_using_custom_root_and_meta
|
20
|
+
with_adapter ActiveModel::Serializer::Adapter::Json do
|
21
|
+
@profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
|
22
|
+
render json: @profile, root: "custom_root", meta: { total: 10 }
|
23
|
+
end
|
15
24
|
end
|
16
25
|
|
17
26
|
def render_using_default_adapter_root
|
@@ -28,6 +37,16 @@ module ActionController
|
|
28
37
|
render json: @profile, root: "profile", adapter: :json_api
|
29
38
|
end
|
30
39
|
|
40
|
+
def render_array_using_custom_root_and_meta
|
41
|
+
with_adapter ActiveModel::Serializer::Adapter::Json do
|
42
|
+
array = [
|
43
|
+
Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }),
|
44
|
+
Profile.new({ name: 'Name 2', description: 'Description 2', comments: 'Comments 2' })
|
45
|
+
]
|
46
|
+
render json: array, root: "custom_root", meta: { total: 10 }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
31
50
|
def render_array_using_implicit_serializer
|
32
51
|
array = [
|
33
52
|
Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }),
|
@@ -139,7 +158,7 @@ module ActionController
|
|
139
158
|
end
|
140
159
|
end
|
141
160
|
|
142
|
-
tests
|
161
|
+
tests ImplicitSerializationTestController
|
143
162
|
|
144
163
|
# We just have Null for now, this will change
|
145
164
|
def test_render_using_implicit_serializer
|
@@ -154,22 +173,17 @@ module ActionController
|
|
154
173
|
assert_equal expected.to_json, @response.body
|
155
174
|
end
|
156
175
|
|
157
|
-
def test_render_using_custom_root
|
158
|
-
get :render_using_custom_root
|
159
|
-
|
160
|
-
assert_equal 'application/json', @response.content_type
|
161
|
-
assert_equal '{"custom_root":{"name":"Name 1","description":"Description 1"}}', @response.body
|
162
|
-
end
|
163
|
-
|
164
176
|
def test_render_using_default_root
|
165
177
|
get :render_using_default_adapter_root
|
166
178
|
|
167
179
|
expected = {
|
168
180
|
data: {
|
169
|
-
name: "Name 1",
|
170
|
-
description: "Description 1",
|
171
181
|
id: assigns(:profile).id.to_s,
|
172
|
-
type: "profiles"
|
182
|
+
type: "profiles",
|
183
|
+
attributes: {
|
184
|
+
name: "Name 1",
|
185
|
+
description: "Description 1"
|
186
|
+
}
|
173
187
|
}
|
174
188
|
}
|
175
189
|
|
@@ -182,10 +196,12 @@ module ActionController
|
|
182
196
|
|
183
197
|
expected = {
|
184
198
|
data: {
|
185
|
-
name: "Name 1",
|
186
|
-
description: "Description 1",
|
187
199
|
id: assigns(:profile).id.to_s,
|
188
|
-
type: "profiles"
|
200
|
+
type: "profiles",
|
201
|
+
attributes: {
|
202
|
+
name: "Name 1",
|
203
|
+
description: "Description 1"
|
204
|
+
}
|
189
205
|
}
|
190
206
|
}
|
191
207
|
|
@@ -217,10 +233,12 @@ module ActionController
|
|
217
233
|
expected = {
|
218
234
|
data: [
|
219
235
|
{
|
220
|
-
name: "Name 1",
|
221
|
-
description: "Description 1",
|
222
236
|
id: assigns(:profiles).first.id.to_s,
|
223
|
-
type: "profiles"
|
237
|
+
type: "profiles",
|
238
|
+
attributes: {
|
239
|
+
name: "Name 1",
|
240
|
+
description: "Description 1"
|
241
|
+
}
|
224
242
|
}
|
225
243
|
],
|
226
244
|
meta: {
|
@@ -319,13 +337,13 @@ module ActionController
|
|
319
337
|
response = JSON.parse(@response.body)
|
320
338
|
|
321
339
|
expected_return = {
|
340
|
+
"id"=>1,
|
341
|
+
"time"=>DateTime.now.to_s,
|
322
342
|
"post" => {
|
323
343
|
"id"=>1,
|
324
344
|
"title"=>"New Post",
|
325
345
|
"body"=>"Body"
|
326
|
-
}
|
327
|
-
"id"=>1,
|
328
|
-
"time"=>DateTime.now.to_s
|
346
|
+
}
|
329
347
|
}
|
330
348
|
|
331
349
|
assert_equal 'application/json', @response.content_type
|