active_model_serializers 0.10.0 → 0.10.7
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 +5 -5
- data/.rubocop.yml +6 -5
- data/.travis.yml +30 -21
- data/CHANGELOG.md +172 -2
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +23 -4
- data/README.md +166 -28
- data/Rakefile +3 -32
- data/active_model_serializers.gemspec +22 -25
- data/appveyor.yml +10 -6
- data/bin/rubocop +38 -0
- data/docs/README.md +2 -1
- data/docs/general/adapters.md +35 -11
- data/docs/general/caching.md +7 -1
- data/docs/general/configuration_options.md +86 -1
- data/docs/general/deserialization.md +1 -1
- data/docs/general/fields.md +31 -0
- data/docs/general/getting_started.md +1 -1
- data/docs/general/logging.md +7 -0
- data/docs/general/rendering.md +63 -25
- data/docs/general/serializers.md +125 -14
- data/docs/howto/add_pagination_links.md +16 -17
- data/docs/howto/add_relationship_links.md +140 -0
- data/docs/howto/add_root_key.md +11 -0
- data/docs/howto/grape_integration.md +42 -0
- data/docs/howto/outside_controller_use.md +12 -4
- data/docs/howto/passing_arbitrary_options.md +2 -2
- data/docs/howto/serialize_poro.md +46 -5
- 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 +67 -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 +62 -10
- data/lib/active_model/serializer/belongs_to_reflection.rb +4 -3
- data/lib/active_model/serializer/collection_serializer.rb +39 -13
- data/lib/active_model/serializer/{caching.rb → concerns/caching.rb} +82 -115
- 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 +3 -3
- data/lib/active_model/serializer/has_one_reflection.rb +1 -4
- data/lib/active_model/serializer/lazy_association.rb +95 -0
- data/lib/active_model/serializer/lint.rb +134 -130
- data/lib/active_model/serializer/reflection.rb +127 -67
- data/lib/active_model/serializer/version.rb +1 -1
- data/lib/active_model/serializer.rb +297 -79
- data/lib/active_model_serializers/adapter/attributes.rb +3 -66
- data/lib/active_model_serializers/adapter/base.rb +39 -39
- data/lib/active_model_serializers/adapter/json_api/deserialization.rb +2 -2
- data/lib/active_model_serializers/adapter/json_api/link.rb +1 -1
- data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +47 -21
- data/lib/active_model_serializers/adapter/json_api/relationship.rb +75 -23
- data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +39 -10
- data/lib/active_model_serializers/adapter/json_api.rb +71 -57
- 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/lookup_chain.rb +80 -0
- data/lib/active_model_serializers/model.rb +109 -28
- 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/test/schema.rb +2 -2
- data/lib/active_model_serializers.rb +16 -1
- data/lib/generators/rails/resource_override.rb +1 -1
- 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/lib/tasks/rubocop.rake +53 -0
- data/test/action_controller/adapter_selector_test.rb +14 -5
- 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/deserialization_test.rb +1 -1
- data/test/action_controller/json_api/errors_test.rb +8 -9
- data/test/action_controller/json_api/fields_test.rb +66 -0
- data/test/action_controller/json_api/linked_test.rb +29 -24
- data/test/action_controller/json_api/pagination_test.rb +31 -23
- data/test/action_controller/json_api/transform_test.rb +11 -3
- data/test/action_controller/lookup_proc_test.rb +49 -0
- data/test/action_controller/namespace_lookup_test.rb +232 -0
- data/test/action_controller/serialization_scope_name_test.rb +12 -6
- data/test/action_controller/serialization_test.rb +12 -9
- data/test/active_model_serializers/json_pointer_test.rb +15 -13
- data/test/active_model_serializers/model_test.rb +137 -4
- data/test/active_model_serializers/railtie_test_isolated.rb +12 -7
- data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +161 -0
- data/test/active_model_serializers/serialization_context_test_isolated.rb +23 -10
- data/test/active_model_serializers/test/schema_test.rb +3 -2
- data/test/adapter/attributes_test.rb +40 -0
- data/test/adapter/json/collection_test.rb +14 -0
- data/test/adapter/json/has_many_test.rb +10 -2
- 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 +12 -3
- data/test/adapter/json_api/has_many_test.rb +49 -20
- data/test/adapter/json_api/include_data_if_sideloaded_test.rb +213 -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 +53 -13
- data/test/adapter/json_api/parse_test.rb +1 -1
- data/test/adapter/json_api/relationship_test.rb +309 -73
- data/test/adapter/json_api/resource_meta_test.rb +3 -3
- data/test/adapter/json_api/transform_test.rb +263 -253
- data/test/adapter/json_api/type_test.rb +168 -36
- data/test/adapter/json_test.rb +8 -7
- data/test/adapter/null_test.rb +1 -2
- data/test/adapter/polymorphic_test.rb +52 -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 +21 -10
- data/test/benchmark/controllers.rb +16 -17
- data/test/benchmark/fixtures.rb +72 -72
- data/test/cache_test.rb +235 -69
- data/test/collection_serializer_test.rb +31 -14
- data/test/fixtures/active_record.rb +45 -10
- data/test/fixtures/poro.rb +124 -181
- data/test/generators/serializer_generator_test.rb +23 -5
- data/test/grape_test.rb +170 -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 +222 -49
- data/test/serializers/attribute_test.rb +5 -3
- data/test/serializers/attributes_test.rb +1 -1
- data/test/serializers/caching_configuration_test_isolated.rb +6 -6
- data/test/serializers/fieldset_test.rb +1 -1
- data/test/serializers/meta_test.rb +12 -6
- data/test/serializers/options_test.rb +17 -6
- data/test/serializers/read_attribute_for_serialization_test.rb +3 -3
- data/test/serializers/reflection_test.rb +427 -0
- data/test/serializers/root_test.rb +1 -1
- data/test/serializers/serialization_test.rb +2 -2
- data/test/serializers/serializer_for_test.rb +12 -10
- data/test/serializers/serializer_for_with_namespace_test.rb +88 -0
- data/test/support/isolated_unit.rb +9 -4
- data/test/support/rails5_shims.rb +8 -2
- data/test/support/rails_app.rb +2 -9
- data/test/support/serialization_testing.rb +31 -5
- data/test/test_helper.rb +13 -0
- metadata +130 -71
- data/.rubocop_todo.yml +0 -167
- data/docs/ARCHITECTURE.md +0 -126
- data/lib/active_model/serializer/associations.rb +0 -100
- data/lib/active_model/serializer/attributes.rb +0 -82
- data/lib/active_model/serializer/collection_reflection.rb +0 -7
- data/lib/active_model/serializer/configuration.rb +0 -35
- data/lib/active_model/serializer/include_tree.rb +0 -111
- data/lib/active_model/serializer/links.rb +0 -35
- data/lib/active_model/serializer/meta.rb +0 -29
- data/lib/active_model/serializer/singular_reflection.rb +0 -7
- data/lib/active_model/serializer/type.rb +0 -25
- data/lib/active_model_serializers/key_transform.rb +0 -70
- data/test/active_model_serializers/key_transform_test.rb +0 -263
- data/test/adapter/json_api/has_many_embed_ids_test.rb +0 -43
- data/test/adapter/json_api/relationships_test.rb +0 -199
- data/test/adapter/json_api/resource_identifier_test.rb +0 -85
- 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
|
@@ -46,15 +46,72 @@ Each adapter has a default key transform configured:
|
|
|
46
46
|
|
|
47
47
|
| Adapter | Default Key Transform |
|
|
48
48
|
|----|----|
|
|
49
|
+
| `Attributes` | `:unaltered` |
|
|
49
50
|
| `Json` | `:unaltered` |
|
|
50
51
|
| `JsonApi` | `:dash` |
|
|
51
52
|
|
|
52
53
|
`config.key_transform` is a global override of the adapter default. Adapters
|
|
53
54
|
still prefer the render option `:key_transform` over this setting.
|
|
54
55
|
|
|
56
|
+
*NOTE: Key transforms can be expensive operations. If key transforms are unnecessary for the
|
|
57
|
+
application, setting `config.key_transform` to `:unaltered` will provide a performance boost.*
|
|
55
58
|
|
|
56
|
-
|
|
59
|
+
##### default_includes
|
|
60
|
+
|
|
61
|
+
What relationships to serialize by default. Default: `'*'`, which includes one level of related
|
|
62
|
+
objects. See [includes](adapters.md#included) for more info.
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
##### serializer_lookup_chain
|
|
66
|
+
|
|
67
|
+
Configures how serializers are searched for. By default, the lookup chain is
|
|
68
|
+
|
|
69
|
+
```ruby
|
|
70
|
+
ActiveModelSerializers::LookupChain::DEFAULT
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
which is shorthand for
|
|
74
|
+
|
|
75
|
+
```ruby
|
|
76
|
+
[
|
|
77
|
+
ActiveModelSerializers::LookupChain::BY_PARENT_SERIALIZER,
|
|
78
|
+
ActiveModelSerializers::LookupChain::BY_NAMESPACE,
|
|
79
|
+
ActiveModelSerializers::LookupChain::BY_RESOURCE_NAMESPACE,
|
|
80
|
+
ActiveModelSerializers::LookupChain::BY_RESOURCE
|
|
81
|
+
]
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Each of the array entries represent a proc. A serializer lookup proc will be yielded 3 arguments. `resource_class`, `serializer_class`, and `namespace`.
|
|
85
|
+
|
|
86
|
+
Note that:
|
|
87
|
+
- `resource_class` is the class of the resource being rendered
|
|
88
|
+
- by default `serializer_class` is `ActiveModel::Serializer`
|
|
89
|
+
- for association lookup it's the "parent" serializer
|
|
90
|
+
- `namespace` correspond to either the controller namespace or the [optionally] specified [namespace render option](./rendering.md#namespace)
|
|
91
|
+
|
|
92
|
+
An example config could be:
|
|
93
|
+
|
|
94
|
+
```ruby
|
|
95
|
+
ActiveModelSerializers.config.serializer_lookup_chain = [
|
|
96
|
+
lambda do |resource_class, serializer_class, namespace|
|
|
97
|
+
"API::#{namespace}::#{resource_class}"
|
|
98
|
+
end
|
|
99
|
+
]
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
If you simply want to add to the existing lookup_chain. Use `unshift`.
|
|
57
103
|
|
|
104
|
+
```ruby
|
|
105
|
+
ActiveModelSerializers.config.serializer_lookup_chain.unshift(
|
|
106
|
+
lambda do |resource_class, serializer_class, namespace|
|
|
107
|
+
# ...
|
|
108
|
+
end
|
|
109
|
+
)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
See [lookup_chain.rb](https://github.com/rails-api/active_model_serializers/blob/master/lib/active_model_serializers/lookup_chain.rb) for further explanations and examples.
|
|
113
|
+
|
|
114
|
+
## JSON API
|
|
58
115
|
|
|
59
116
|
##### jsonapi_resource_type
|
|
60
117
|
|
|
@@ -67,6 +124,19 @@ Possible values:
|
|
|
67
124
|
- `:singular`
|
|
68
125
|
- `:plural` (default)
|
|
69
126
|
|
|
127
|
+
##### jsonapi_namespace_separator
|
|
128
|
+
|
|
129
|
+
Sets separator string for namespaced models to render `type` attribute.
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
| Separator | Example: Admin::User |
|
|
133
|
+
|----|----|
|
|
134
|
+
| `'-'` (default) | 'admin-users'
|
|
135
|
+
| `'--'` (recommended) | 'admin--users'
|
|
136
|
+
|
|
137
|
+
See [Recommendation for dasherizing (kebab-case-ing) namespaced object, such as `Admin::User`](https://github.com/json-api/json-api/issues/850)
|
|
138
|
+
for more discussion.
|
|
139
|
+
|
|
70
140
|
##### jsonapi_include_toplevel_object
|
|
71
141
|
|
|
72
142
|
Include a [top level jsonapi member](http://jsonapi.org/format/#document-jsonapi-object)
|
|
@@ -93,6 +163,21 @@ Default: `{}`.
|
|
|
93
163
|
|
|
94
164
|
*Used when `jsonapi_include_toplevel_object` is `true`*
|
|
95
165
|
|
|
166
|
+
##### jsonapi_use_foreign_key_on_belongs_to_relationship
|
|
167
|
+
|
|
168
|
+
When true, the relationship will determine its resource object identifier
|
|
169
|
+
without calling the association or its serializer. This can be useful when calling
|
|
170
|
+
the association object is triggering unnecessary queries.
|
|
171
|
+
|
|
172
|
+
For example, if a `comment` belongs to a `post`, and the comment
|
|
173
|
+
uses the foreign key `post_id`, we can determine the resource object
|
|
174
|
+
identifier `id` as `comment.post_id` and the `type` from the association options.
|
|
175
|
+
Or quite simply, it behaves as `belongs_to :post, type: :posts, foreign_key: :post_id`.
|
|
176
|
+
|
|
177
|
+
Note: This option has *no effect* on polymorphic associations as we cannot reliably
|
|
178
|
+
determine the associated object's type without instantiating it.
|
|
179
|
+
|
|
180
|
+
Default: `false`.
|
|
96
181
|
|
|
97
182
|
## Hooks
|
|
98
183
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
[Back to Guides](../README.md)
|
|
2
|
+
|
|
3
|
+
# Fields
|
|
4
|
+
|
|
5
|
+
If for any reason, you need to restrict the fields returned, you should use `fields` option.
|
|
6
|
+
|
|
7
|
+
For example, if you have a serializer like this
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
class UserSerializer < ActiveModel::Serializer
|
|
11
|
+
attributes :access_token, :first_name, :last_name
|
|
12
|
+
end
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
and in a specific controller, you want to return `access_token` only, `fields` will help you:
|
|
16
|
+
|
|
17
|
+
```ruby
|
|
18
|
+
class AnonymousController < ApplicationController
|
|
19
|
+
def create
|
|
20
|
+
render json: User.create(activation_state: 'anonymous'), fields: [:access_token], status: 201
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Note that this is only valid for the `json` and `attributes` adapter. For the `json_api` adapter, you would use
|
|
26
|
+
|
|
27
|
+
```ruby
|
|
28
|
+
render json: @user, fields: { users: [:access_token] }
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Where `users` is the JSONAPI type.
|
data/docs/general/logging.md
CHANGED
|
@@ -12,3 +12,10 @@ You may customize the logger in an initializer, for example:
|
|
|
12
12
|
```ruby
|
|
13
13
|
ActiveModelSerializers.logger = Logger.new(STDOUT)
|
|
14
14
|
```
|
|
15
|
+
|
|
16
|
+
You can also disable the logger, just put this in `config/initializers/active_model_serializers.rb`:
|
|
17
|
+
|
|
18
|
+
```ruby
|
|
19
|
+
require 'active_model_serializers'
|
|
20
|
+
ActiveSupport::Notifications.unsubscribe(ActiveModelSerializers::Logging::RENDER_EVENT)
|
|
21
|
+
```
|
data/docs/general/rendering.md
CHANGED
|
@@ -48,42 +48,36 @@ render json: @posts, serializer: CollectionSerializer, each_serializer: PostPrev
|
|
|
48
48
|
|
|
49
49
|
## Serializing non-ActiveRecord objects
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
[ActiveModel::Serializer::Lint::Tests](../../lib/active_model/serializer/lint.rb#L17).
|
|
53
|
-
|
|
54
|
-
See the ActiveModelSerializers::Model for a base class that implements the full
|
|
55
|
-
API for a plain-old Ruby object (PORO).
|
|
51
|
+
See [README](../../README.md#what-does-a-serializable-resource-look-like)
|
|
56
52
|
|
|
57
53
|
## SerializableResource options
|
|
58
54
|
|
|
59
|
-
|
|
60
|
-
are partitioned into `serializer_opts` and `adapter_opts`. `adapter_opts` are passed to new Adapters;
|
|
61
|
-
`serializer_opts` are passed to new Serializers.
|
|
62
|
-
|
|
63
|
-
The `adapter_opts` are specified in [ActiveModelSerializers::SerializableResource::ADAPTER_OPTIONS](../../lib/active_model_serializers/serializable_resource.rb#L5).
|
|
64
|
-
The `serializer_opts` are the remaining options.
|
|
65
|
-
|
|
66
|
-
(In Rails, the `options` are also passed to the `as_json(options)` or `to_json(options)`
|
|
67
|
-
methods on the resource serialization by the Rails JSON renderer. They are, therefore, important
|
|
68
|
-
to know about, but not part of ActiveModelSerializers.)
|
|
69
|
-
|
|
70
|
-
See [ARCHITECTURE](../ARCHITECTURE.md) for more information.
|
|
55
|
+
See [README](../../README.md#activemodelserializersserializableresource)
|
|
71
56
|
|
|
72
57
|
### adapter_opts
|
|
73
58
|
|
|
74
59
|
#### fields
|
|
75
60
|
|
|
76
|
-
|
|
61
|
+
If you are using `json` or `attributes` adapter
|
|
62
|
+
```ruby
|
|
63
|
+
render json: @user, fields: [:access_token]
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
See [Fields](fields.md) for more information.
|
|
77
67
|
|
|
78
68
|
#### adapter
|
|
79
69
|
|
|
80
|
-
|
|
70
|
+
This option lets you explicitly set the adapter to be used by passing a registered adapter. Your options are `:attributes`, `:json`, and `:json_api`.
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
ActiveModel::Serializer.config.adapter = :json_api
|
|
74
|
+
```
|
|
81
75
|
|
|
82
76
|
#### key_transform
|
|
83
77
|
|
|
84
78
|
```render json: posts, each_serializer: PostSerializer, key_transform: :camel_lower```
|
|
85
79
|
|
|
86
|
-
See [Key Transforms](key_transforms.md) for more
|
|
80
|
+
See [Key Transforms](key_transforms.md) for more information.
|
|
87
81
|
|
|
88
82
|
#### meta
|
|
89
83
|
|
|
@@ -209,7 +203,7 @@ link(:link_name) { url_for(controller: 'controller_name', action: 'index', only_
|
|
|
209
203
|
|
|
210
204
|
#### include
|
|
211
205
|
|
|
212
|
-
|
|
206
|
+
See [Adapters: Include Option](/docs/general/adapters.md#include-option).
|
|
213
207
|
|
|
214
208
|
#### Overriding the root key
|
|
215
209
|
|
|
@@ -234,17 +228,61 @@ This will be rendered as:
|
|
|
234
228
|
```
|
|
235
229
|
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
230
|
|
|
231
|
+
#### namespace
|
|
232
|
+
|
|
233
|
+
The namespace for serializer lookup is based on the controller.
|
|
234
|
+
|
|
235
|
+
To configure the implicit namespace, in your controller, create a before filter
|
|
236
|
+
|
|
237
|
+
```ruby
|
|
238
|
+
before_action do
|
|
239
|
+
self.namespace_for_serializer = Api::V2
|
|
240
|
+
end
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
`namespace` can also be passed in as a render option:
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
```ruby
|
|
247
|
+
@post = Post.first
|
|
248
|
+
render json: @post, namespace: Api::V2
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
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.
|
|
252
|
+
|
|
253
|
+
The `namespace` can be any object whose namespace can be represented by string interpolation (i.e. by calling to_s)
|
|
254
|
+
- Module `Api::V2`
|
|
255
|
+
- String `'Api::V2'`
|
|
256
|
+
- Symbol `:'Api::V2'`
|
|
257
|
+
|
|
258
|
+
Note that by using a string and symbol, Ruby will assume the namespace is defined at the top level.
|
|
259
|
+
|
|
260
|
+
|
|
237
261
|
#### serializer
|
|
238
262
|
|
|
239
|
-
|
|
263
|
+
Specify which serializer to use if you want to use a serializer other than the default.
|
|
264
|
+
|
|
265
|
+
For a single resource:
|
|
266
|
+
|
|
267
|
+
```ruby
|
|
268
|
+
@post = Post.first
|
|
269
|
+
render json: @post, serializer: SpecialPostSerializer
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
To specify which serializer to use on individual items in a collection (i.e., an `index` action), use `each_serializer`:
|
|
273
|
+
|
|
274
|
+
```ruby
|
|
275
|
+
@posts = Post.all
|
|
276
|
+
render json: @posts, each_serializer: SpecialPostSerializer
|
|
277
|
+
```
|
|
240
278
|
|
|
241
279
|
#### scope
|
|
242
280
|
|
|
243
|
-
|
|
281
|
+
See [Serializers: Scope](/docs/general/serializers.md#scope).
|
|
244
282
|
|
|
245
283
|
#### scope_name
|
|
246
284
|
|
|
247
|
-
|
|
285
|
+
See [Serializers: Scope](/docs/general/serializers.md#scope).
|
|
248
286
|
|
|
249
287
|
## Using a serializer without `render`
|
|
250
288
|
|
|
@@ -252,4 +290,4 @@ See [Usage outside of a controller](../howto/outside_controller_use.md#serializi
|
|
|
252
290
|
|
|
253
291
|
## Pagination
|
|
254
292
|
|
|
255
|
-
See [How to add pagination links](
|
|
293
|
+
See [How to add pagination links](../howto/add_pagination_links.md).
|
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
|
|
|
@@ -53,6 +64,10 @@ Where:
|
|
|
53
64
|
- `unless:`
|
|
54
65
|
- `virtual_value:`
|
|
55
66
|
- `polymorphic:` defines if polymorphic relation type should be nested in serialized association.
|
|
67
|
+
- `type:` the resource type as used by JSON:API, especially on a `belongs_to` relationship.
|
|
68
|
+
- `class_name:` used to determine `type` when `type` not given
|
|
69
|
+
- `foreign_key:` used by JSON:API on a `belongs_to` relationship to avoid unnecessarily loading the association object.
|
|
70
|
+
- `namespace:` used when looking up the serializer and `serializer` is not given. Falls back to the parent serializer's `:namespace` instance options, which, when present, comes from the render options. See [Rendering#namespace](rendering.md#namespace] for more details.
|
|
56
71
|
- optional: `&block` is a context that returns the association's attributes.
|
|
57
72
|
- prevents `association_name` method from being called.
|
|
58
73
|
- return value of block is used as the association value.
|
|
@@ -129,7 +144,7 @@ class PictureSerializer < ActiveModel::Serializer
|
|
|
129
144
|
end
|
|
130
145
|
```
|
|
131
146
|
|
|
132
|
-
For more context, see the [tests](../../test/adapter/polymorphic_test.rb) for each adapter.
|
|
147
|
+
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
148
|
|
|
134
149
|
### Caching
|
|
135
150
|
|
|
@@ -162,18 +177,25 @@ end
|
|
|
162
177
|
|
|
163
178
|
#### ::type
|
|
164
179
|
|
|
165
|
-
|
|
180
|
+
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.
|
|
181
|
+
|
|
182
|
+
When using the `:json` adapter, the `::type` method defines the name of the root element.
|
|
183
|
+
|
|
166
184
|
It either takes a `String` or `Symbol` as parameter.
|
|
167
185
|
|
|
168
|
-
Note: This method is useful only when using the `:json_api` adapter.
|
|
186
|
+
Note: This method is useful only when using the `:json_api` or `:json` adapter.
|
|
169
187
|
|
|
170
188
|
Examples:
|
|
171
189
|
```ruby
|
|
172
190
|
class UserProfileSerializer < ActiveModel::Serializer
|
|
173
191
|
type 'profile'
|
|
192
|
+
|
|
193
|
+
attribute :name
|
|
174
194
|
end
|
|
175
195
|
class AuthorProfileSerializer < ActiveModel::Serializer
|
|
176
196
|
type :profile
|
|
197
|
+
|
|
198
|
+
attribute :name
|
|
177
199
|
end
|
|
178
200
|
```
|
|
179
201
|
|
|
@@ -183,7 +205,20 @@ With the `:json_api` adapter, the previous serializers would be rendered as:
|
|
|
183
205
|
{
|
|
184
206
|
"data": {
|
|
185
207
|
"id": "1",
|
|
186
|
-
"type": "profile"
|
|
208
|
+
"type": "profile",
|
|
209
|
+
"attributes": {
|
|
210
|
+
"name": "Julia"
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
With the `:json` adapter, the previous serializer would be rendered as:
|
|
217
|
+
|
|
218
|
+
``` json
|
|
219
|
+
{
|
|
220
|
+
"profile": {
|
|
221
|
+
"name": "Julia"
|
|
187
222
|
}
|
|
188
223
|
}
|
|
189
224
|
```
|
|
@@ -194,10 +229,10 @@ With the `:json_api` adapter, the previous serializers would be rendered as:
|
|
|
194
229
|
link :self do
|
|
195
230
|
href "https://example.com/link_author/#{object.id}"
|
|
196
231
|
end
|
|
197
|
-
link
|
|
198
|
-
link
|
|
232
|
+
link(:author) { link_author_url(object) }
|
|
233
|
+
link(:link_authors) { link_authors_url }
|
|
199
234
|
link :other, 'https://example.com/resource'
|
|
200
|
-
link
|
|
235
|
+
link(:posts) { link_author_posts_url(object) }
|
|
201
236
|
```
|
|
202
237
|
|
|
203
238
|
#### #object
|
|
@@ -206,7 +241,17 @@ The object being serialized.
|
|
|
206
241
|
|
|
207
242
|
#### #root
|
|
208
243
|
|
|
209
|
-
|
|
244
|
+
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.
|
|
245
|
+
By default, the resource root comes from the `model_name` of the serialized object's class.
|
|
246
|
+
|
|
247
|
+
There are several ways to specify root:
|
|
248
|
+
* [Overriding the root key](rendering.md#overriding-the-root-key)
|
|
249
|
+
* [Setting `type`](serializers.md#type)
|
|
250
|
+
* Specifying the `root` option, e.g. `root: 'specific_name'`, during the serializer's initialization:
|
|
251
|
+
|
|
252
|
+
```ruby
|
|
253
|
+
ActiveModelSerializers::SerializableResource.new(foo, root: 'bar')
|
|
254
|
+
```
|
|
210
255
|
|
|
211
256
|
#### #scope
|
|
212
257
|
|
|
@@ -249,13 +294,15 @@ end
|
|
|
249
294
|
Whether you write the method as above or as `object.comments.where(created_by: scope)`
|
|
250
295
|
is a matter of preference (assuming `scope_name` has been set).
|
|
251
296
|
|
|
297
|
+
Keep in mind that the scope can be set to any available controller reference. This can be utilized to provide access to any other data scopes or presentation helpers.
|
|
298
|
+
|
|
252
299
|
##### Controller Authorization Context
|
|
253
300
|
|
|
254
301
|
In the controller, the scope/scope_name options are equal to
|
|
255
302
|
the [`serialization_scope`method](https://github.com/rails-api/active_model_serializers/blob/d02cd30fe55a3ea85e1d351b6e039620903c1871/lib/action_controller/serialization.rb#L13-L20),
|
|
256
303
|
which is `:current_user`, by default.
|
|
257
304
|
|
|
258
|
-
|
|
305
|
+
Specifically, the `scope_name` is defaulted to `:current_user`, and may be set as
|
|
259
306
|
`serialization_scope :view_context`. The `scope` is set to `send(scope_name)` when `scope_name` is
|
|
260
307
|
present and the controller responds to `scope_name`.
|
|
261
308
|
|
|
@@ -266,7 +313,7 @@ current authorization scope when you call `render :json`.
|
|
|
266
313
|
called on every request. This was [also a problem](https://github.com/rails-api/active_model_serializers/pull/1252#issuecomment-159810477)
|
|
267
314
|
in [`0.9`](https://github.com/rails-api/active_model_serializers/tree/0-9-stable#customizing-scope).
|
|
268
315
|
|
|
269
|
-
We can change the scope from `current_user` to `view_context`.
|
|
316
|
+
We can change the scope from `current_user` to `view_context`, which is included in subclasses of `ActionController::Base`.
|
|
270
317
|
|
|
271
318
|
```diff
|
|
272
319
|
class SomeController < ActionController::Base
|
|
@@ -303,17 +350,65 @@ So that when we render the `#edit` action, we'll get
|
|
|
303
350
|
|
|
304
351
|
Where `can_edit` is `view_context.current_user.admin?` (true).
|
|
305
352
|
|
|
353
|
+
You can also tell what to set as `serialization_scope` for specific actions.
|
|
354
|
+
|
|
355
|
+
For example, use `admin_user` only for `Admin::PostSerializer` and `current_user` for rest.
|
|
356
|
+
|
|
357
|
+
```ruby
|
|
358
|
+
class PostsController < ActionController::Base
|
|
359
|
+
|
|
360
|
+
before_action only: :edit do
|
|
361
|
+
self.class.serialization_scope :admin_user
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
def show
|
|
365
|
+
render json: @post, serializer: PostSerializer
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
def edit
|
|
369
|
+
@post.save
|
|
370
|
+
render json: @post, serializer: Admin::PostSerializer
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
private
|
|
374
|
+
|
|
375
|
+
def admin_user
|
|
376
|
+
User.new(id: 2, name: 'Bob', admin: true)
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
def current_user
|
|
380
|
+
User.new(id: 2, name: 'Bob', admin: false)
|
|
381
|
+
end
|
|
382
|
+
end
|
|
383
|
+
```
|
|
384
|
+
Note that any controller reference which provides the desired scope is acceptable, such as another controller method for loading a different resource or reference to helpers. For example, `ActionController::API` does not include `ActionView::ViewContext`, and would need a different reference for passing any helpers into a serializer via `serialization_scope`.
|
|
385
|
+
|
|
306
386
|
#### #read_attribute_for_serialization(key)
|
|
307
387
|
|
|
308
388
|
The serialized value for a given key. e.g. `read_attribute_for_serialization(:title) #=> 'Hello World'`
|
|
309
389
|
|
|
310
390
|
#### #links
|
|
311
391
|
|
|
312
|
-
|
|
392
|
+
Allows you to modify the `links` node. By default, this node will be populated with the attributes set using the [::link](#link) method. Using `links: nil` will remove the `links` node.
|
|
393
|
+
|
|
394
|
+
```ruby
|
|
395
|
+
ActiveModelSerializers::SerializableResource.new(
|
|
396
|
+
@post,
|
|
397
|
+
adapter: :json_api,
|
|
398
|
+
links: {
|
|
399
|
+
self: {
|
|
400
|
+
href: 'http://example.com/posts',
|
|
401
|
+
meta: {
|
|
402
|
+
stuff: 'value'
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
)
|
|
407
|
+
```
|
|
313
408
|
|
|
314
409
|
#### #json_key
|
|
315
410
|
|
|
316
|
-
|
|
411
|
+
Returns the key used by the adapter as the resource root. See [root](#root) for more information.
|
|
317
412
|
|
|
318
413
|
## Examples
|
|
319
414
|
|
|
@@ -370,3 +465,19 @@ class PostSerializer < ActiveModel::Serializer
|
|
|
370
465
|
end
|
|
371
466
|
end
|
|
372
467
|
```
|
|
468
|
+
|
|
469
|
+
## Overriding association serializer lookup
|
|
470
|
+
|
|
471
|
+
If you want to define a specific serializer lookup for your associations, you can override
|
|
472
|
+
the `ActiveModel::Serializer.serializer_for` method to return a serializer class based on defined conditions.
|
|
473
|
+
|
|
474
|
+
```ruby
|
|
475
|
+
class MySerializer < ActiveModel::Serializer
|
|
476
|
+
def self.serializer_for(model, options)
|
|
477
|
+
return SparseAdminSerializer if model.class == 'Admin'
|
|
478
|
+
super
|
|
479
|
+
end
|
|
480
|
+
|
|
481
|
+
# the rest of the serializer
|
|
482
|
+
end
|
|
483
|
+
```
|
|
@@ -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
|
|
|
@@ -72,18 +72,18 @@ ActiveModelSerializers pagination relies on a paginated collection with the meth
|
|
|
72
72
|
|
|
73
73
|
### JSON adapter
|
|
74
74
|
|
|
75
|
-
If you are using `JSON` adapter, pagination links will not be included automatically, but it is possible to do so using `meta` key.
|
|
75
|
+
If you are not using `JSON` adapter, pagination links will not be included automatically, but it is possible to do so using `meta` key.
|
|
76
76
|
|
|
77
77
|
Add this method to your base API controller.
|
|
78
78
|
|
|
79
79
|
```ruby
|
|
80
|
-
def pagination_dict(
|
|
80
|
+
def pagination_dict(collection)
|
|
81
81
|
{
|
|
82
|
-
current_page:
|
|
83
|
-
next_page:
|
|
84
|
-
prev_page:
|
|
85
|
-
total_pages:
|
|
86
|
-
total_count:
|
|
82
|
+
current_page: collection.current_page,
|
|
83
|
+
next_page: collection.next_page,
|
|
84
|
+
prev_page: collection.prev_page, # use collection.previous_page when using will_paginate
|
|
85
|
+
total_pages: collection.total_pages,
|
|
86
|
+
total_count: collection.total_count
|
|
87
87
|
}
|
|
88
88
|
end
|
|
89
89
|
```
|
|
@@ -117,23 +117,22 @@ ex.
|
|
|
117
117
|
You can also achieve the same result if you have a helper method that adds the pagination info in the meta tag. For instance, in your action specify a custom serializer.
|
|
118
118
|
|
|
119
119
|
```ruby
|
|
120
|
-
render json: @posts, each_serializer: PostPreviewSerializer, meta: meta_attributes(@
|
|
120
|
+
render json: @posts, each_serializer: PostPreviewSerializer, meta: meta_attributes(@posts)
|
|
121
121
|
```
|
|
122
122
|
|
|
123
123
|
```ruby
|
|
124
124
|
#expects pagination!
|
|
125
|
-
def meta_attributes(
|
|
125
|
+
def meta_attributes(collection, extra_meta = {})
|
|
126
126
|
{
|
|
127
|
-
current_page:
|
|
128
|
-
next_page:
|
|
129
|
-
prev_page:
|
|
130
|
-
total_pages:
|
|
131
|
-
total_count:
|
|
127
|
+
current_page: collection.current_page,
|
|
128
|
+
next_page: collection.next_page,
|
|
129
|
+
prev_page: collection.prev_page, # use collection.previous_page when using will_paginate
|
|
130
|
+
total_pages: collection.total_pages,
|
|
131
|
+
total_count: collection.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.
|