active_model_serializers 0.10.0 → 0.10.3
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/.rubocop.yml +2 -4
- data/.travis.yml +9 -1
- data/CHANGELOG.md +81 -2
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +5 -2
- data/README.md +24 -24
- data/Rakefile +3 -3
- data/active_model_serializers.gemspec +20 -24
- data/docs/ARCHITECTURE.md +6 -7
- data/docs/README.md +2 -0
- data/docs/general/adapters.md +4 -2
- data/docs/general/caching.md +7 -1
- data/docs/general/configuration_options.md +70 -1
- data/docs/general/deserialization.md +1 -1
- data/docs/general/fields.md +31 -0
- data/docs/general/rendering.md +42 -3
- data/docs/general/serializers.md +97 -8
- data/docs/howto/add_pagination_links.md +4 -5
- data/docs/howto/add_relationship_links.md +137 -0
- data/docs/howto/add_root_key.md +4 -0
- data/docs/howto/grape_integration.md +42 -0
- data/docs/howto/outside_controller_use.md +9 -2
- data/docs/howto/passing_arbitrary_options.md +2 -2
- data/docs/howto/test.md +2 -0
- data/docs/howto/upgrade_from_0_8_to_0_10.md +265 -0
- data/docs/integrations/ember-and-json-api.md +64 -32
- data/docs/jsonapi/schema.md +1 -1
- data/lib/action_controller/serialization.rb +13 -3
- data/lib/active_model/serializer/adapter/base.rb +2 -0
- data/lib/active_model/serializer/array_serializer.rb +8 -5
- data/lib/active_model/serializer/association.rb +19 -4
- data/lib/active_model/serializer/belongs_to_reflection.rb +0 -3
- data/lib/active_model/serializer/collection_serializer.rb +35 -12
- data/lib/active_model/serializer/{associations.rb → concerns/associations.rb} +13 -11
- data/lib/active_model/serializer/{attributes.rb → concerns/attributes.rb} +0 -0
- data/lib/active_model/serializer/{caching.rb → concerns/caching.rb} +72 -113
- data/lib/active_model/serializer/{configuration.rb → concerns/configuration.rb} +25 -1
- data/lib/active_model/serializer/{links.rb → concerns/links.rb} +0 -0
- data/lib/active_model/serializer/{meta.rb → concerns/meta.rb} +0 -0
- data/lib/active_model/serializer/{type.rb → concerns/type.rb} +0 -0
- data/lib/active_model/serializer/error_serializer.rb +11 -7
- data/lib/active_model/serializer/errors_serializer.rb +25 -20
- data/lib/active_model/serializer/has_many_reflection.rb +0 -3
- data/lib/active_model/serializer/has_one_reflection.rb +0 -3
- data/lib/active_model/serializer/lint.rb +134 -130
- data/lib/active_model/serializer/reflection.rb +37 -21
- data/lib/active_model/serializer/version.rb +1 -1
- data/lib/active_model/serializer.rb +76 -37
- data/lib/active_model_serializers/adapter/attributes.rb +3 -66
- data/lib/active_model_serializers/adapter/base.rb +38 -38
- data/lib/active_model_serializers/adapter/json_api/link.rb +1 -1
- data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +8 -1
- data/lib/active_model_serializers/adapter/json_api/relationship.rb +30 -19
- data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +23 -9
- data/lib/active_model_serializers/adapter/json_api.rb +44 -43
- data/lib/active_model_serializers/adapter.rb +6 -0
- data/lib/active_model_serializers/deprecate.rb +1 -2
- data/lib/active_model_serializers/deserialization.rb +2 -0
- data/lib/active_model_serializers/key_transform.rb +4 -0
- data/lib/active_model_serializers/lookup_chain.rb +80 -0
- data/lib/active_model_serializers/model.rb +4 -2
- data/lib/active_model_serializers/railtie.rb +3 -1
- data/lib/active_model_serializers/register_jsonapi_renderer.rb +44 -31
- data/lib/active_model_serializers/serializable_resource.rb +6 -5
- data/lib/active_model_serializers/serialization_context.rb +10 -3
- data/lib/active_model_serializers.rb +7 -0
- data/lib/generators/rails/serializer_generator.rb +4 -4
- data/lib/grape/active_model_serializers.rb +7 -5
- data/lib/grape/formatters/active_model_serializers.rb +19 -2
- data/lib/grape/helpers/active_model_serializers.rb +1 -0
- data/test/action_controller/adapter_selector_test.rb +4 -4
- data/test/action_controller/explicit_serializer_test.rb +5 -4
- data/test/action_controller/json/include_test.rb +106 -27
- data/test/action_controller/json_api/errors_test.rb +6 -7
- data/test/action_controller/json_api/fields_test.rb +57 -0
- data/test/action_controller/json_api/linked_test.rb +29 -24
- data/test/action_controller/json_api/pagination_test.rb +19 -19
- data/test/action_controller/json_api/transform_test.rb +3 -3
- data/test/action_controller/lookup_proc_test.rb +49 -0
- data/test/action_controller/namespace_lookup_test.rb +226 -0
- data/test/action_controller/serialization_test.rb +10 -7
- data/test/active_model_serializers/json_pointer_test.rb +15 -13
- data/test/active_model_serializers/key_transform_test.rb +286 -252
- data/test/active_model_serializers/model_test.rb +17 -4
- data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +143 -0
- data/test/active_model_serializers/serialization_context_test_isolated.rb +23 -10
- data/test/adapter/attributes_test.rb +43 -0
- data/test/adapter/json/collection_test.rb +14 -0
- data/test/adapter/json/transform_test.rb +15 -15
- data/test/adapter/json_api/collection_test.rb +4 -3
- data/test/adapter/json_api/errors_test.rb +17 -19
- data/test/adapter/json_api/fields_test.rb +4 -3
- data/test/adapter/json_api/has_many_test.rb +39 -18
- data/test/adapter/json_api/include_data_if_sideloaded_test.rb +166 -0
- data/test/adapter/json_api/json_api_test.rb +5 -7
- data/test/adapter/json_api/linked_test.rb +33 -12
- data/test/adapter/json_api/links_test.rb +4 -2
- data/test/adapter/json_api/pagination_links_test.rb +35 -8
- data/test/adapter/json_api/relationship_test.rb +309 -73
- data/test/adapter/json_api/resource_identifier_test.rb +27 -2
- data/test/adapter/json_api/resource_meta_test.rb +3 -3
- data/test/adapter/json_api/transform_test.rb +255 -253
- data/test/adapter/json_api/type_test.rb +1 -1
- data/test/adapter/json_test.rb +8 -7
- data/test/adapter/null_test.rb +1 -2
- data/test/adapter/polymorphic_test.rb +5 -5
- data/test/adapter_test.rb +1 -1
- data/test/benchmark/app.rb +1 -1
- data/test/benchmark/benchmarking_support.rb +1 -1
- data/test/benchmark/bm_active_record.rb +81 -0
- data/test/benchmark/bm_adapter.rb +38 -0
- data/test/benchmark/bm_caching.rb +16 -16
- data/test/benchmark/bm_lookup_chain.rb +83 -0
- data/test/benchmark/bm_transform.rb +16 -5
- data/test/benchmark/controllers.rb +16 -17
- data/test/benchmark/fixtures.rb +72 -72
- data/test/cache_test.rb +143 -49
- data/test/collection_serializer_test.rb +3 -3
- data/test/fixtures/poro.rb +52 -48
- data/test/generators/serializer_generator_test.rb +22 -5
- data/test/grape_test.rb +152 -56
- data/test/lint_test.rb +1 -1
- data/test/logger_test.rb +13 -11
- data/test/serializable_resource_test.rb +18 -22
- data/test/serializers/association_macros_test.rb +3 -2
- data/test/serializers/associations_test.rb +107 -32
- data/test/serializers/attribute_test.rb +2 -2
- data/test/serializers/attributes_test.rb +1 -1
- data/test/serializers/fieldset_test.rb +1 -1
- data/test/serializers/meta_test.rb +12 -6
- data/test/serializers/root_test.rb +1 -1
- data/test/serializers/serializer_for_test.rb +6 -4
- data/test/serializers/serializer_for_with_namespace_test.rb +87 -0
- data/test/support/isolated_unit.rb +5 -2
- data/test/support/rails5_shims.rb +8 -2
- data/test/support/rails_app.rb +0 -9
- data/test/support/serialization_testing.rb +23 -5
- data/test/test_helper.rb +1 -0
- metadata +85 -34
- data/.rubocop_todo.yml +0 -167
- data/lib/active_model/serializer/include_tree.rb +0 -111
- data/test/adapter/json_api/relationships_test.rb +0 -199
- data/test/include_tree/from_include_args_test.rb +0 -26
- data/test/include_tree/from_string_test.rb +0 -94
- data/test/include_tree/include_args_to_hash_test.rb +0 -64
data/docs/general/rendering.md
CHANGED
@@ -73,17 +73,26 @@ See [ARCHITECTURE](../ARCHITECTURE.md) for more information.
|
|
73
73
|
|
74
74
|
#### fields
|
75
75
|
|
76
|
-
|
76
|
+
If you are using `json` or `attributes` adapter
|
77
|
+
```ruby
|
78
|
+
render json: @user, fields: [:access_token]
|
79
|
+
```
|
80
|
+
|
81
|
+
See [Fields](fields.md) for more information.
|
77
82
|
|
78
83
|
#### adapter
|
79
84
|
|
80
|
-
|
85
|
+
This option lets you explicitly set the adapter to be used by passing a registered adapter. Your options are `:attributes`, `:json`, and `:json_api`.
|
86
|
+
|
87
|
+
```
|
88
|
+
ActiveModel::Serializer.config.adapter = :json_api
|
89
|
+
```
|
81
90
|
|
82
91
|
#### key_transform
|
83
92
|
|
84
93
|
```render json: posts, each_serializer: PostSerializer, key_transform: :camel_lower```
|
85
94
|
|
86
|
-
See [Key Transforms](key_transforms.md) for more
|
95
|
+
See [Key Transforms](key_transforms.md) for more information.
|
87
96
|
|
88
97
|
#### meta
|
89
98
|
|
@@ -234,6 +243,36 @@ This will be rendered as:
|
|
234
243
|
```
|
235
244
|
Note: the `Attributes` adapter (default) does not include a resource root. You also will not be able to create a single top-level root if you are using the :json_api adapter.
|
236
245
|
|
246
|
+
#### namespace
|
247
|
+
|
248
|
+
The namespace for serializer lookup is based on the controller.
|
249
|
+
|
250
|
+
To configure the implicit namespace, in your controller, create a before filter
|
251
|
+
|
252
|
+
```ruby
|
253
|
+
before_action do
|
254
|
+
self.namespace_for_serializer = Api::V2
|
255
|
+
end
|
256
|
+
```
|
257
|
+
|
258
|
+
`namespace` can also be passed in as a render option:
|
259
|
+
|
260
|
+
|
261
|
+
```ruby
|
262
|
+
@post = Post.first
|
263
|
+
render json: @post, namespace: Api::V2
|
264
|
+
```
|
265
|
+
|
266
|
+
This tells the serializer lookup to check for the existence of `Api::V2::PostSerializer`, and if any relations are rendered with `@post`, they will also utilize the `Api::V2` namespace.
|
267
|
+
|
268
|
+
The `namespace` can be any object whose namespace can be represented by string interpolation (i.e. by calling to_s)
|
269
|
+
- Module `Api::V2`
|
270
|
+
- String `'Api::V2'`
|
271
|
+
- Symbol `:'Api::V2'`
|
272
|
+
|
273
|
+
Note that by using a string and symbol, Ruby will assume the namespace is defined at the top level.
|
274
|
+
|
275
|
+
|
237
276
|
#### serializer
|
238
277
|
|
239
278
|
PR please :)
|
data/docs/general/serializers.md
CHANGED
@@ -31,10 +31,21 @@ Serialization of the resource `title`
|
|
31
31
|
|---------------------------- |-------------|
|
32
32
|
| `attribute :title` | `{ title: 'Some Title' } `
|
33
33
|
| `attribute :title, key: :name` | `{ name: 'Some Title' } `
|
34
|
-
| `attribute
|
34
|
+
| `attribute(:title) { 'A Different Title'}` | `{ title: 'A Different Title' } `
|
35
35
|
| `attribute :title`<br>`def title 'A Different Title' end` | `{ title: 'A Different Title' }`
|
36
36
|
|
37
|
-
|
37
|
+
An `if` or `unless` option can make an attribute conditional. It takes a symbol of a method name on the serializer, or a lambda literal.
|
38
|
+
|
39
|
+
e.g.
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
attribute :private_data, if: :is_current_user?
|
43
|
+
attribute :another_private_data, if: -> { scope.admin? }
|
44
|
+
|
45
|
+
def is_current_user?
|
46
|
+
object.id == current_user.id
|
47
|
+
end
|
48
|
+
```
|
38
49
|
|
39
50
|
### Associations
|
40
51
|
|
@@ -129,7 +140,7 @@ class PictureSerializer < ActiveModel::Serializer
|
|
129
140
|
end
|
130
141
|
```
|
131
142
|
|
132
|
-
For more context, see the [tests](../../test/adapter/polymorphic_test.rb) for each adapter.
|
143
|
+
You can specify the serializers by [overriding serializer_for](serializers.md#overriding-association-serializer-lookup). For more context about polymorphic relationships, see the [tests](../../test/adapter/polymorphic_test.rb) for each adapter.
|
133
144
|
|
134
145
|
### Caching
|
135
146
|
|
@@ -162,18 +173,25 @@ end
|
|
162
173
|
|
163
174
|
#### ::type
|
164
175
|
|
165
|
-
|
176
|
+
When using the `:json_api` adapter, the `::type` method defines the JSONAPI [type](http://jsonapi.org/format/#document-resource-object-identification) that will be rendered for this serializer.
|
177
|
+
|
178
|
+
When using the `:json` adapter, the `::type` method defines the name of the root element.
|
179
|
+
|
166
180
|
It either takes a `String` or `Symbol` as parameter.
|
167
181
|
|
168
|
-
Note: This method is useful only when using the `:json_api` adapter.
|
182
|
+
Note: This method is useful only when using the `:json_api` or `:json` adapter.
|
169
183
|
|
170
184
|
Examples:
|
171
185
|
```ruby
|
172
186
|
class UserProfileSerializer < ActiveModel::Serializer
|
173
187
|
type 'profile'
|
188
|
+
|
189
|
+
attribute :name
|
174
190
|
end
|
175
191
|
class AuthorProfileSerializer < ActiveModel::Serializer
|
176
192
|
type :profile
|
193
|
+
|
194
|
+
attribute :name
|
177
195
|
end
|
178
196
|
```
|
179
197
|
|
@@ -183,7 +201,20 @@ With the `:json_api` adapter, the previous serializers would be rendered as:
|
|
183
201
|
{
|
184
202
|
"data": {
|
185
203
|
"id": "1",
|
186
|
-
"type": "profile"
|
204
|
+
"type": "profile",
|
205
|
+
"attributes": {
|
206
|
+
"name": "Julia"
|
207
|
+
}
|
208
|
+
}
|
209
|
+
}
|
210
|
+
```
|
211
|
+
|
212
|
+
With the `:json` adapter, the previous serializer would be rendered as:
|
213
|
+
|
214
|
+
``` json
|
215
|
+
{
|
216
|
+
"profile": {
|
217
|
+
"name": "Julia"
|
187
218
|
}
|
188
219
|
}
|
189
220
|
```
|
@@ -206,7 +237,17 @@ The object being serialized.
|
|
206
237
|
|
207
238
|
#### #root
|
208
239
|
|
209
|
-
|
240
|
+
Resource root which is included in `JSON` adapter. As you can see at [Adapters Document](adapters.md), `Attribute` adapter (default) and `JSON API` adapter does not include root at top level.
|
241
|
+
By default, the resource root comes from the `model_name` of the serialized object's class.
|
242
|
+
|
243
|
+
There are several ways to specify root:
|
244
|
+
* [Overriding the root key](rendering.md#overriding-the-root-key)
|
245
|
+
* [Setting `type`](serializers.md#type)
|
246
|
+
* Specifying the `root` option, e.g. `root: 'specific_name'`, during the serializer's initialization:
|
247
|
+
|
248
|
+
```ruby
|
249
|
+
ActiveModelSerializers::SerializableResource.new(foo, root: 'bar')
|
250
|
+
```
|
210
251
|
|
211
252
|
#### #scope
|
212
253
|
|
@@ -255,7 +296,7 @@ In the controller, the scope/scope_name options are equal to
|
|
255
296
|
the [`serialization_scope`method](https://github.com/rails-api/active_model_serializers/blob/d02cd30fe55a3ea85e1d351b6e039620903c1871/lib/action_controller/serialization.rb#L13-L20),
|
256
297
|
which is `:current_user`, by default.
|
257
298
|
|
258
|
-
|
299
|
+
Specifically, the `scope_name` is defaulted to `:current_user`, and may be set as
|
259
300
|
`serialization_scope :view_context`. The `scope` is set to `send(scope_name)` when `scope_name` is
|
260
301
|
present and the controller responds to `scope_name`.
|
261
302
|
|
@@ -303,6 +344,38 @@ So that when we render the `#edit` action, we'll get
|
|
303
344
|
|
304
345
|
Where `can_edit` is `view_context.current_user.admin?` (true).
|
305
346
|
|
347
|
+
You can also tell what to set as `serialization_scope` for specific actions.
|
348
|
+
|
349
|
+
For example, use `admin_user` only for `Admin::PostSerializer` and `current_user` for rest.
|
350
|
+
|
351
|
+
```ruby
|
352
|
+
class PostsController < ActionController::Base
|
353
|
+
|
354
|
+
before_action only: :edit do
|
355
|
+
self.class.serialization_scope :admin_user
|
356
|
+
end
|
357
|
+
|
358
|
+
def show
|
359
|
+
render json: @post, serializer: PostSerializer
|
360
|
+
end
|
361
|
+
|
362
|
+
def edit
|
363
|
+
@post.save
|
364
|
+
render json: @post, serializer: Admin::PostSerializer
|
365
|
+
end
|
366
|
+
|
367
|
+
private
|
368
|
+
|
369
|
+
def admin_user
|
370
|
+
User.new(id: 2, name: 'Bob', admin: true)
|
371
|
+
end
|
372
|
+
|
373
|
+
def current_user
|
374
|
+
User.new(id: 2, name: 'Bob', admin: false)
|
375
|
+
end
|
376
|
+
end
|
377
|
+
```
|
378
|
+
|
306
379
|
#### #read_attribute_for_serialization(key)
|
307
380
|
|
308
381
|
The serialized value for a given key. e.g. `read_attribute_for_serialization(:title) #=> 'Hello World'`
|
@@ -370,3 +443,19 @@ class PostSerializer < ActiveModel::Serializer
|
|
370
443
|
end
|
371
444
|
end
|
372
445
|
```
|
446
|
+
|
447
|
+
## Overriding association serializer lookup
|
448
|
+
|
449
|
+
If you want to define a specific serializer lookup for your associations, you can override
|
450
|
+
the `ActiveModel::Serializer.serializer_for` method to return a serializer class based on defined conditions.
|
451
|
+
|
452
|
+
```ruby
|
453
|
+
class MySerializer < ActiveModel::Serializer
|
454
|
+
def self.serializer_for(model, options)
|
455
|
+
return SparseAdminSerializer if model.class == 'Admin'
|
456
|
+
super
|
457
|
+
end
|
458
|
+
|
459
|
+
# the rest of the serializer
|
460
|
+
end
|
461
|
+
```
|
@@ -10,9 +10,9 @@ the resource is paginated and if you are using the ```JsonApi``` adapter.
|
|
10
10
|
If you want pagination links in your response, use [Kaminari](https://github.com/amatsuda/kaminari)
|
11
11
|
or [WillPaginate](https://github.com/mislav/will_paginate).
|
12
12
|
|
13
|
-
Although the
|
13
|
+
Although the other adapters do not have this feature, it is possible to
|
14
14
|
implement pagination links to `JSON` adapter. For more information about it,
|
15
|
-
please
|
15
|
+
please check our docs.
|
16
16
|
|
17
17
|
###### Kaminari examples
|
18
18
|
|
@@ -81,7 +81,7 @@ def pagination_dict(object)
|
|
81
81
|
{
|
82
82
|
current_page: object.current_page,
|
83
83
|
next_page: object.next_page,
|
84
|
-
prev_page: object.prev_page,
|
84
|
+
prev_page: object.prev_page, # use object.previous_page when using will_paginate
|
85
85
|
total_pages: object.total_pages,
|
86
86
|
total_count: object.total_count
|
87
87
|
}
|
@@ -126,14 +126,13 @@ def meta_attributes(resource, extra_meta = {})
|
|
126
126
|
{
|
127
127
|
current_page: resource.current_page,
|
128
128
|
next_page: resource.next_page,
|
129
|
-
prev_page: resource.prev_page,
|
129
|
+
prev_page: resource.prev_page, # use resource.previous_page when using will_paginate
|
130
130
|
total_pages: resource.total_pages,
|
131
131
|
total_count: resource.total_count
|
132
132
|
}.merge(extra_meta)
|
133
133
|
end
|
134
134
|
```
|
135
135
|
|
136
|
-
|
137
136
|
### Attributes adapter
|
138
137
|
|
139
138
|
This adapter does not allow us to use `meta` key, due to that it is not possible to add pagination links.
|
@@ -0,0 +1,137 @@
|
|
1
|
+
[Back to Guides](../README.md)
|
2
|
+
|
3
|
+
# How to add relationship links
|
4
|
+
|
5
|
+
ActiveModelSerializers offers you many ways to add links in your JSON, depending on your needs.
|
6
|
+
The most common use case for links is supporting nested resources.
|
7
|
+
|
8
|
+
The following examples are without included relationship data (`include` param is empty),
|
9
|
+
specifically the following Rails controller was used for these examples:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
class Api::V1::UsersController < ApplicationController
|
13
|
+
def show
|
14
|
+
render jsonapi: User.find(params[:id]),
|
15
|
+
serializer: Api::V1::UserSerializer,
|
16
|
+
include: []
|
17
|
+
end
|
18
|
+
```
|
19
|
+
|
20
|
+
Bear in mind though that ActiveModelSerializers are [framework-agnostic](outside_controller_use.md), Rails is just a common example here.
|
21
|
+
|
22
|
+
### Links as an attribute of a resource
|
23
|
+
**This is applicable to JSONAPI, JSON and Attributes adapters**
|
24
|
+
|
25
|
+
You can define an attribute in the resource, named `links`.
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
class Api::V1::UserSerializer < ActiveModel::Serializer
|
29
|
+
attributes :id, :name, :links
|
30
|
+
|
31
|
+
def links
|
32
|
+
{
|
33
|
+
self: api_v1_user_path(object.id),
|
34
|
+
microposts: api_v1_microposts_path(user_id: object.id)
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
```
|
39
|
+
|
40
|
+
This will resilt in (example is in jsonapi adapter):
|
41
|
+
```json
|
42
|
+
{
|
43
|
+
"data": {
|
44
|
+
"id": "1",
|
45
|
+
"type": "users",
|
46
|
+
"attributes": {
|
47
|
+
"name": "Example User",
|
48
|
+
"links": {
|
49
|
+
"self": "/api/v1/users/1",
|
50
|
+
"microposts": "/api/v1/microposts?user_id=1"
|
51
|
+
}
|
52
|
+
}
|
53
|
+
}
|
54
|
+
}
|
55
|
+
```
|
56
|
+
|
57
|
+
|
58
|
+
### Links as a property of the resource definiton
|
59
|
+
**This is only applicable to JSONAPI adapter**
|
60
|
+
|
61
|
+
You can use the `links` class method to define the links you need in the resource's primary data.
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
class Api::V1::UserSerializer < ActiveModel::Serializer
|
65
|
+
attributes :id, :name
|
66
|
+
|
67
|
+
link(:self) { api_v1_user_path(object.id) }
|
68
|
+
link(:microposts) { api_v1_microposts_path(user_id: object.id) }
|
69
|
+
end
|
70
|
+
```
|
71
|
+
|
72
|
+
This will resilt in (example is in jsonapi adapter):
|
73
|
+
```json
|
74
|
+
{
|
75
|
+
"data": {
|
76
|
+
"id": "1",
|
77
|
+
"type": "users",
|
78
|
+
"attributes": {
|
79
|
+
"name": "Example User"
|
80
|
+
},
|
81
|
+
"links": {
|
82
|
+
"self": "/api/v1/users/1",
|
83
|
+
"microposts": "/api/v1/microposts?user_id=1"
|
84
|
+
}
|
85
|
+
}
|
86
|
+
}
|
87
|
+
```
|
88
|
+
|
89
|
+
### Links that follow the JSONAPI spec
|
90
|
+
**This is only applicable to JSONAPI adapter**
|
91
|
+
|
92
|
+
If you have a JSONAPI-strict client that you are working with (like `ember-data`)
|
93
|
+
you need to construct the links inside the relationships. Also the link to fetch the
|
94
|
+
relationship data must be under the `related` attribute, whereas to manipulate the
|
95
|
+
relationship (in case of many-to-many relationship) must be under the `self` attribute.
|
96
|
+
|
97
|
+
You can find more info in the [spec](http://jsonapi.org/format/#document-resource-object-relationships).
|
98
|
+
|
99
|
+
Here is how you can do this:
|
100
|
+
|
101
|
+
```ruby
|
102
|
+
class Api::V1::UserSerializer < ActiveModel::Serializer
|
103
|
+
attributes :id, :name
|
104
|
+
|
105
|
+
has_many :microposts, serializer: Api::V1::MicropostSerializer do
|
106
|
+
link(:related) { api_v1_microposts_path(user_id: object.id) }
|
107
|
+
end
|
108
|
+
|
109
|
+
#this is needed to avoid n+1, gem core devs are working to remove this necessity
|
110
|
+
#more on: https://github.com/rails-api/active_model_serializers/issues/1325
|
111
|
+
def microposts
|
112
|
+
object.microposts.loaded ? object.microposts : object.microposts.none
|
113
|
+
end
|
114
|
+
end
|
115
|
+
```
|
116
|
+
|
117
|
+
This will result in:
|
118
|
+
|
119
|
+
```json
|
120
|
+
{
|
121
|
+
"data": {
|
122
|
+
"id": "1",
|
123
|
+
"type": "users",
|
124
|
+
"attributes": {
|
125
|
+
"name": "Example User"
|
126
|
+
},
|
127
|
+
"relationships": {
|
128
|
+
"microposts": {
|
129
|
+
"data": [],
|
130
|
+
"links": {
|
131
|
+
"related": "/api/v1/microposts?user_id=1"
|
132
|
+
}
|
133
|
+
}
|
134
|
+
}
|
135
|
+
}
|
136
|
+
}
|
137
|
+
```
|
data/docs/howto/add_root_key.md
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
[Back to Guides](../README.md)
|
2
|
+
|
1
3
|
# How to add root key
|
2
4
|
|
3
5
|
Add the root key to your API is quite simple with ActiveModelSerializers. The **Adapter** is what determines the format of your JSON response. The default adapter is the ```Attributes``` which doesn't have the root key, so your response is something similar to:
|
@@ -49,3 +51,5 @@ or if it returns a collection:
|
|
49
51
|
]
|
50
52
|
}
|
51
53
|
```
|
54
|
+
|
55
|
+
[There are several ways to specify root](../general/serializers.md#root) when using the JSON adapter.
|
@@ -0,0 +1,42 @@
|
|
1
|
+
[Back to Guides](../README.md)
|
2
|
+
|
3
|
+
The ActiveModelSerializers grape formatter relies on the existence of `env['grape.request']` which is implemeted by `Grape::Middleware::Globals`. You can meet his dependency by calling it before mounting the endpoints.
|
4
|
+
|
5
|
+
In the simpliest way:
|
6
|
+
|
7
|
+
```
|
8
|
+
class API < Grape::API
|
9
|
+
# @note Make sure this is above you're first +mount+
|
10
|
+
use Grape::Middleware::Globals
|
11
|
+
end
|
12
|
+
```
|
13
|
+
|
14
|
+
or more like what is shown in current Grape tutorials:
|
15
|
+
|
16
|
+
```
|
17
|
+
module MyApi
|
18
|
+
class ApiBase < Grape::API
|
19
|
+
use Grape::Middleware::Globals
|
20
|
+
|
21
|
+
require 'grape/active_model_serializers'
|
22
|
+
include Grape::ActiveModelSerializers
|
23
|
+
|
24
|
+
mount MyApi::V1::ApiBase
|
25
|
+
end
|
26
|
+
end
|
27
|
+
```
|
28
|
+
|
29
|
+
You could meet this dependency with your own middleware. The invocation might look like:
|
30
|
+
|
31
|
+
```
|
32
|
+
module MyApi
|
33
|
+
class ApiBase < Grape::API
|
34
|
+
use My::Middleware::Thingamabob
|
35
|
+
|
36
|
+
require 'grape/active_model_serializers'
|
37
|
+
include Grape::ActiveModelSerializers
|
38
|
+
|
39
|
+
mount MyApi::V1::ApiBase
|
40
|
+
end
|
41
|
+
end
|
42
|
+
```
|
@@ -19,10 +19,11 @@ serializable_resource = ActiveModelSerializers::SerializableResource.new(post, o
|
|
19
19
|
# Convert your resource into json
|
20
20
|
model_json = serializable_resource.as_json
|
21
21
|
```
|
22
|
+
The object that is passed to `ActiveModelSerializers::SerializableResource.new` can be a single resource or a collection.
|
22
23
|
|
23
24
|
### Looking up the Serializer for a Resource
|
24
25
|
|
25
|
-
If you want to retrieve
|
26
|
+
If you want to retrieve the serializer class for a specific resource, you can do the following:
|
26
27
|
|
27
28
|
```ruby
|
28
29
|
# Create our resource
|
@@ -41,7 +42,13 @@ You could also retrieve the serializer via:
|
|
41
42
|
ActiveModelSerializers::SerializableResource.new(post, options).serializer
|
42
43
|
```
|
43
44
|
|
44
|
-
Both approaches will return
|
45
|
+
Both approaches will return the serializer class that will be used for the resource.
|
46
|
+
|
47
|
+
Additionally, you could retrieve the serializer instance for the resource via:
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
ActiveModelSerializers::SerializableResource.new(post, options).serializer_instance
|
51
|
+
```
|
45
52
|
|
46
53
|
## Serializing before controller render
|
47
54
|
|
@@ -11,7 +11,7 @@ For example, we could pass in a field, such as `user_id` into our serializer.
|
|
11
11
|
```ruby
|
12
12
|
# posts_controller.rb
|
13
13
|
class PostsController < ApplicationController
|
14
|
-
def dashboard
|
14
|
+
def dashboard
|
15
15
|
render json: @post, user_id: 12
|
16
16
|
end
|
17
17
|
end
|
@@ -20,7 +20,7 @@ end
|
|
20
20
|
class PostSerializer < ActiveModel::Serializer
|
21
21
|
attributes :id, :title, :body
|
22
22
|
|
23
|
-
def comments_by_me
|
23
|
+
def comments_by_me
|
24
24
|
Comments.where(user_id: instance_options[:user_id], post_id: object.id)
|
25
25
|
end
|
26
26
|
end
|