active_model_serializers 0.10.0.rc1 → 0.10.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -2
  3. data/Gemfile +1 -1
  4. data/README.md +6 -3
  5. data/lib/action_controller/serialization.rb +9 -1
  6. data/lib/active_model/serializer.rb +15 -21
  7. data/lib/active_model/serializer/adapter.rb +13 -4
  8. data/lib/active_model/serializer/adapter/flatten_json.rb +12 -0
  9. data/lib/active_model/serializer/adapter/fragment_cache.rb +5 -5
  10. data/lib/active_model/serializer/adapter/json.rb +8 -10
  11. data/lib/active_model/serializer/adapter/json_api.rb +34 -30
  12. data/lib/active_model/serializer/adapter/json_api/fragment_cache.rb +3 -2
  13. data/lib/active_model/serializer/array_serializer.rb +8 -5
  14. data/lib/active_model/serializer/configuration.rb +1 -1
  15. data/lib/active_model/serializer/fieldset.rb +2 -2
  16. data/lib/active_model/serializer/railtie.rb +8 -0
  17. data/lib/active_model/serializer/version.rb +1 -1
  18. data/lib/active_model_serializers.rb +1 -0
  19. data/lib/generators/serializer/resource_override.rb +12 -0
  20. data/test/action_controller/adapter_selector_test.rb +7 -5
  21. data/test/action_controller/explicit_serializer_test.rb +33 -9
  22. data/test/action_controller/json_api_linked_test.rb +25 -19
  23. data/test/action_controller/rescue_from_test.rb +32 -0
  24. data/test/action_controller/serialization_scope_name_test.rb +2 -2
  25. data/test/action_controller/serialization_test.rb +41 -23
  26. data/test/adapter/fragment_cache_test.rb +1 -1
  27. data/test/adapter/json/belongs_to_test.rb +9 -2
  28. data/test/adapter/json/collection_test.rb +16 -2
  29. data/test/adapter/json/has_many_test.rb +1 -1
  30. data/test/adapter/json_api/belongs_to_test.rb +45 -35
  31. data/test/adapter/json_api/collection_test.rb +30 -23
  32. data/test/adapter/json_api/has_many_embed_ids_test.rb +2 -2
  33. data/test/adapter/json_api/has_many_explicit_serializer_test.rb +14 -14
  34. data/test/adapter/json_api/has_many_test.rb +22 -18
  35. data/test/adapter/json_api/has_one_test.rb +8 -6
  36. data/test/adapter/json_api/linked_test.rb +97 -71
  37. data/test/adapter/json_test.rb +1 -1
  38. data/test/adapter_test.rb +1 -1
  39. data/test/array_serializer_test.rb +14 -0
  40. data/test/fixtures/poro.rb +31 -7
  41. data/test/generators/scaffold_controller_generator_test.rb +24 -0
  42. data/test/{serializers/generators_test.rb → generators/serializer_generator_test.rb} +2 -10
  43. data/test/serializers/adapter_for_test.rb +1 -1
  44. data/test/serializers/associations_test.rb +21 -0
  45. data/test/serializers/attribute_test.rb +16 -1
  46. data/test/serializers/attributes_test.rb +35 -0
  47. data/test/serializers/cache_test.rb +14 -4
  48. data/test/serializers/configuration_test.rb +1 -1
  49. data/test/serializers/meta_test.rb +38 -9
  50. data/test/serializers/serializer_for_test.rb +9 -0
  51. data/test/test_helper.rb +10 -7
  52. 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].merge(core_non_cached[1]) : core_non_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
- hash.merge no_root_non_cache.merge no_root_cache
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
- options.merge!(root: nil)
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
- @objects.first.json_key if @objects.first
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)
@@ -6,7 +6,7 @@ module ActiveModel
6
6
 
7
7
  included do |base|
8
8
  base.config.array_serializer = ActiveModel::Serializer::ArraySerializer
9
- base.config.adapter = :json
9
+ base.config.adapter = :flatten_json
10
10
  end
11
11
  end
12
12
  end
@@ -12,8 +12,8 @@ module ActiveModel
12
12
  end
13
13
 
14
14
  def fields_for(serializer)
15
- key = serializer.json_key || serializer.class.root_name
16
- fields[key.to_sym]
15
+ key = serializer.json_key
16
+ fields[key.to_sym] || fields[key.pluralize.to_sym]
17
17
  end
18
18
 
19
19
  private
@@ -0,0 +1,8 @@
1
+ module ActiveModel
2
+ class Railtie < Rails::Railtie
3
+ initializer 'generators' do |app|
4
+ app.load_generators
5
+ require 'generators/serializer/resource_override'
6
+ end
7
+ end
8
+ end
@@ -1,5 +1,5 @@
1
1
  module ActiveModel
2
2
  class Serializer
3
- VERSION = "0.10.0.rc1"
3
+ VERSION = "0.10.0.rc2"
4
4
  end
5
5
  end
@@ -2,6 +2,7 @@ require 'active_model'
2
2
  require 'active_model/serializer/version'
3
3
  require 'active_model/serializer'
4
4
  require 'active_model/serializer/fieldset'
5
+ require 'active_model/serializer/railtie'
5
6
 
6
7
  begin
7
8
  require 'action_controller'
@@ -0,0 +1,12 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/rails/resource/resource_generator'
3
+
4
+ module Rails
5
+ module Generators
6
+ class ResourceGenerator
7
+ def add_serializer
8
+ invoke 'serializer'
9
+ end
10
+ end
11
+ end
12
+ end
@@ -3,7 +3,7 @@ require 'test_helper'
3
3
  module ActionController
4
4
  module Serialization
5
5
  class AdapterSelectorTest < ActionController::TestCase
6
- class MyController < ActionController::Base
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 MyController
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 MyController < ActionController::Base
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 MyController
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
- 'paginated' => [
75
- { 'name' => 'Name 1' },
76
- { 'name' => 'Name 2' }
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 test_render_array_using_explicit_serializer
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 MyController < ActionController::Base
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 MyController
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
- "name" => "Steve K.",
105
- "links" => {
106
- "posts" => { "linkage" => [] },
107
- "roles" => { "linkage" => [{ "type" =>"roles", "id" => "1" }, { "type" =>"roles", "id" => "2" }] },
108
- "bio" => { "linkage" => nil }
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
- "name" => "admin",
114
- "description" => nil,
115
- "slug" => "admin-1",
116
- "links" => {
117
- "author" => { "linkage" => { "type" =>"authors", "id" => "1" } }
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
- "name" => "colab",
123
- "description" => nil,
124
- "slug" => "colab-2",
125
- "links" => {
126
- "author" => { "linkage" => { "type" =>"authors", "id" => "1" } }
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":{"admin?":false,"id":"1","type":"users"}}', @response.body
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":{"admin?":true,"id":"1","type":"users"}}', @response.body
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 MyController < ActionController::Base
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
- @profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
14
- render json: @profile, root: "custom_root"
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 MyController
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