active_model_serializers 0.10.0 → 0.10.9
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 +10 -5
- data/.travis.yml +41 -21
- data/CHANGELOG.md +200 -2
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +25 -4
- data/README.md +166 -28
- data/Rakefile +5 -32
- data/active_model_serializers.gemspec +23 -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 +137 -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 +15 -3
- data/lib/active_model/serializable_resource.rb +2 -0
- data/lib/active_model/serializer/adapter/attributes.rb +2 -0
- data/lib/active_model/serializer/adapter/base.rb +4 -0
- data/lib/active_model/serializer/adapter/json.rb +2 -0
- data/lib/active_model/serializer/adapter/json_api.rb +2 -0
- data/lib/active_model/serializer/adapter/null.rb +2 -0
- data/lib/active_model/serializer/adapter.rb +2 -0
- data/lib/active_model/serializer/array_serializer.rb +10 -5
- data/lib/active_model/serializer/association.rb +64 -10
- data/lib/active_model/serializer/attribute.rb +2 -0
- data/lib/active_model/serializer/belongs_to_reflection.rb +6 -3
- data/lib/active_model/serializer/collection_serializer.rb +39 -13
- data/lib/active_model/serializer/{caching.rb → concerns/caching.rb} +87 -116
- data/lib/active_model/serializer/error_serializer.rb +13 -7
- data/lib/active_model/serializer/errors_serializer.rb +27 -20
- data/lib/active_model/serializer/field.rb +2 -0
- data/lib/active_model/serializer/fieldset.rb +2 -0
- data/lib/active_model/serializer/has_many_reflection.rb +5 -3
- data/lib/active_model/serializer/has_one_reflection.rb +3 -4
- data/lib/active_model/serializer/lazy_association.rb +99 -0
- data/lib/active_model/serializer/link.rb +23 -0
- data/lib/active_model/serializer/lint.rb +136 -130
- data/lib/active_model/serializer/null.rb +2 -0
- data/lib/active_model/serializer/reflection.rb +132 -67
- data/lib/active_model/serializer/version.rb +3 -1
- data/lib/active_model/serializer.rb +308 -82
- data/lib/active_model_serializers/adapter/attributes.rb +5 -66
- data/lib/active_model_serializers/adapter/base.rb +41 -39
- data/lib/active_model_serializers/adapter/json.rb +2 -0
- data/lib/active_model_serializers/adapter/json_api/deserialization.rb +4 -2
- data/lib/active_model_serializers/adapter/json_api/error.rb +2 -0
- data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +2 -0
- data/lib/active_model_serializers/adapter/json_api/link.rb +3 -1
- data/lib/active_model_serializers/adapter/json_api/meta.rb +2 -0
- data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +49 -21
- data/lib/active_model_serializers/adapter/json_api/relationship.rb +77 -23
- data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +41 -10
- data/lib/active_model_serializers/adapter/json_api.rb +84 -65
- data/lib/active_model_serializers/adapter/null.rb +2 -0
- data/lib/active_model_serializers/adapter.rb +9 -1
- data/lib/active_model_serializers/callbacks.rb +2 -0
- data/lib/active_model_serializers/deprecate.rb +3 -2
- data/lib/active_model_serializers/deserialization.rb +4 -0
- data/lib/active_model_serializers/json_pointer.rb +2 -0
- data/lib/active_model_serializers/logging.rb +2 -0
- data/lib/active_model_serializers/lookup_chain.rb +82 -0
- data/lib/active_model_serializers/model.rb +111 -28
- data/lib/active_model_serializers/railtie.rb +7 -1
- data/lib/active_model_serializers/register_jsonapi_renderer.rb +46 -31
- data/lib/active_model_serializers/serializable_resource.rb +10 -7
- data/lib/active_model_serializers/serialization_context.rb +12 -3
- data/lib/active_model_serializers/test/schema.rb +4 -2
- data/lib/active_model_serializers/test/serializer.rb +2 -0
- data/lib/active_model_serializers/test.rb +2 -0
- data/lib/active_model_serializers.rb +35 -10
- data/lib/generators/rails/resource_override.rb +3 -1
- data/lib/generators/rails/serializer_generator.rb +6 -4
- data/lib/grape/active_model_serializers.rb +9 -5
- data/lib/grape/formatters/active_model_serializers.rb +21 -2
- data/lib/grape/helpers/active_model_serializers.rb +3 -0
- data/lib/tasks/rubocop.rake +55 -0
- data/test/action_controller/adapter_selector_test.rb +16 -5
- data/test/action_controller/explicit_serializer_test.rb +7 -4
- data/test/action_controller/json/include_test.rb +108 -27
- data/test/action_controller/json_api/deserialization_test.rb +3 -1
- data/test/action_controller/json_api/errors_test.rb +10 -9
- data/test/action_controller/json_api/fields_test.rb +68 -0
- data/test/action_controller/json_api/linked_test.rb +31 -24
- data/test/action_controller/json_api/pagination_test.rb +33 -23
- data/test/action_controller/json_api/transform_test.rb +13 -3
- data/test/action_controller/lookup_proc_test.rb +51 -0
- data/test/action_controller/namespace_lookup_test.rb +234 -0
- data/test/action_controller/serialization_scope_name_test.rb +14 -6
- data/test/action_controller/serialization_test.rb +23 -12
- data/test/active_model_serializers/adapter_for_test.rb +2 -0
- data/test/active_model_serializers/json_pointer_test.rb +17 -13
- data/test/active_model_serializers/logging_test.rb +2 -0
- data/test/active_model_serializers/model_test.rb +139 -4
- data/test/active_model_serializers/railtie_test_isolated.rb +14 -7
- data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +163 -0
- data/test/active_model_serializers/serialization_context_test_isolated.rb +25 -10
- data/test/active_model_serializers/test/schema_test.rb +5 -2
- data/test/active_model_serializers/test/serializer_test.rb +2 -0
- data/test/active_record_test.rb +2 -0
- data/test/adapter/attributes_test.rb +42 -0
- data/test/adapter/deprecation_test.rb +2 -0
- data/test/adapter/json/belongs_to_test.rb +2 -0
- data/test/adapter/json/collection_test.rb +16 -0
- data/test/adapter/json/has_many_test.rb +12 -2
- data/test/adapter/json/transform_test.rb +17 -15
- data/test/adapter/json_api/belongs_to_test.rb +2 -0
- data/test/adapter/json_api/collection_test.rb +6 -3
- data/test/adapter/json_api/errors_test.rb +19 -19
- data/test/adapter/json_api/fields_test.rb +14 -3
- data/test/adapter/json_api/has_many_explicit_serializer_test.rb +2 -0
- data/test/adapter/json_api/has_many_test.rb +51 -20
- data/test/adapter/json_api/has_one_test.rb +2 -0
- data/test/adapter/json_api/include_data_if_sideloaded_test.rb +215 -0
- data/test/adapter/json_api/json_api_test.rb +7 -7
- data/test/adapter/json_api/linked_test.rb +35 -12
- data/test/adapter/json_api/links_test.rb +22 -3
- data/test/adapter/json_api/pagination_links_test.rb +55 -13
- data/test/adapter/json_api/parse_test.rb +3 -1
- data/test/adapter/json_api/relationship_test.rb +311 -73
- data/test/adapter/json_api/resource_meta_test.rb +5 -3
- data/test/adapter/json_api/toplevel_jsonapi_test.rb +2 -0
- data/test/adapter/json_api/transform_test.rb +265 -253
- data/test/adapter/json_api/type_test.rb +170 -36
- data/test/adapter/json_test.rb +10 -7
- data/test/adapter/null_test.rb +3 -2
- data/test/adapter/polymorphic_test.rb +54 -5
- data/test/adapter_test.rb +3 -1
- data/test/array_serializer_test.rb +2 -0
- data/test/benchmark/app.rb +3 -1
- data/test/benchmark/benchmarking_support.rb +3 -1
- data/test/benchmark/bm_active_record.rb +83 -0
- data/test/benchmark/bm_adapter.rb +40 -0
- data/test/benchmark/bm_caching.rb +18 -16
- data/test/benchmark/bm_lookup_chain.rb +85 -0
- data/test/benchmark/bm_transform.rb +23 -10
- data/test/benchmark/controllers.rb +18 -17
- data/test/benchmark/fixtures.rb +74 -72
- data/test/cache_test.rb +301 -69
- data/test/collection_serializer_test.rb +33 -14
- data/test/fixtures/active_record.rb +47 -10
- data/test/fixtures/poro.rb +128 -183
- data/test/generators/scaffold_controller_generator_test.rb +2 -0
- data/test/generators/serializer_generator_test.rb +25 -5
- data/test/grape_test.rb +172 -56
- data/test/lint_test.rb +3 -1
- data/test/logger_test.rb +15 -11
- data/test/poro_test.rb +2 -0
- data/test/serializable_resource_test.rb +20 -22
- data/test/serializers/association_macros_test.rb +5 -2
- data/test/serializers/associations_test.rb +274 -49
- data/test/serializers/attribute_test.rb +7 -3
- data/test/serializers/attributes_test.rb +3 -1
- data/test/serializers/caching_configuration_test_isolated.rb +8 -6
- data/test/serializers/configuration_test.rb +2 -0
- data/test/serializers/fieldset_test.rb +3 -1
- data/test/serializers/meta_test.rb +14 -6
- data/test/serializers/options_test.rb +19 -6
- data/test/serializers/read_attribute_for_serialization_test.rb +5 -3
- data/test/serializers/reflection_test.rb +481 -0
- data/test/serializers/root_test.rb +3 -1
- data/test/serializers/serialization_test.rb +4 -2
- data/test/serializers/serializer_for_test.rb +14 -10
- data/test/serializers/serializer_for_with_namespace_test.rb +90 -0
- data/test/support/isolated_unit.rb +11 -4
- data/test/support/rails5_shims.rb +10 -2
- data/test/support/rails_app.rb +4 -9
- data/test/support/serialization_testing.rb +33 -5
- data/test/test_helper.rb +15 -0
- metadata +126 -46
- 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:` the (String) model name used to determine `type`, when `type` is not given. e.g. `class_name: "Comment"` would imply the type `comments`
|
|
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.
|
|
@@ -66,6 +81,7 @@ e.g.
|
|
|
66
81
|
```ruby
|
|
67
82
|
has_one :bio
|
|
68
83
|
has_one :blog, key: :site
|
|
84
|
+
has_one :blog, class_name: "Blog"
|
|
69
85
|
has_one :maker, virtual_value: { id: 1 }
|
|
70
86
|
|
|
71
87
|
has_one :blog do |serializer|
|
|
@@ -99,6 +115,7 @@ e.g.
|
|
|
99
115
|
has_many :comments
|
|
100
116
|
has_many :comments, key: :reviews
|
|
101
117
|
has_many :comments, serializer: CommentPreviewSerializer
|
|
118
|
+
has_many :comments, class_name: "Comment"
|
|
102
119
|
has_many :reviews, virtual_value: [{ id: 1 }, { id: 2 }]
|
|
103
120
|
has_many :comments, key: :last_comments do
|
|
104
121
|
last(1)
|
|
@@ -112,6 +129,7 @@ e.g.
|
|
|
112
129
|
```ruby
|
|
113
130
|
belongs_to :author, serializer: AuthorPreviewSerializer
|
|
114
131
|
belongs_to :author, key: :writer
|
|
132
|
+
belongs_to :author, class_name: "Author"
|
|
115
133
|
belongs_to :post
|
|
116
134
|
belongs_to :blog
|
|
117
135
|
def blog
|
|
@@ -129,7 +147,7 @@ class PictureSerializer < ActiveModel::Serializer
|
|
|
129
147
|
end
|
|
130
148
|
```
|
|
131
149
|
|
|
132
|
-
For more context, see the [tests](../../test/adapter/polymorphic_test.rb) for each adapter.
|
|
150
|
+
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
151
|
|
|
134
152
|
### Caching
|
|
135
153
|
|
|
@@ -162,18 +180,25 @@ end
|
|
|
162
180
|
|
|
163
181
|
#### ::type
|
|
164
182
|
|
|
165
|
-
|
|
183
|
+
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.
|
|
184
|
+
|
|
185
|
+
When using the `:json` adapter, the `::type` method defines the name of the root element.
|
|
186
|
+
|
|
166
187
|
It either takes a `String` or `Symbol` as parameter.
|
|
167
188
|
|
|
168
|
-
Note: This method is useful only when using the `:json_api` adapter.
|
|
189
|
+
Note: This method is useful only when using the `:json_api` or `:json` adapter.
|
|
169
190
|
|
|
170
191
|
Examples:
|
|
171
192
|
```ruby
|
|
172
193
|
class UserProfileSerializer < ActiveModel::Serializer
|
|
173
194
|
type 'profile'
|
|
195
|
+
|
|
196
|
+
attribute :name
|
|
174
197
|
end
|
|
175
198
|
class AuthorProfileSerializer < ActiveModel::Serializer
|
|
176
199
|
type :profile
|
|
200
|
+
|
|
201
|
+
attribute :name
|
|
177
202
|
end
|
|
178
203
|
```
|
|
179
204
|
|
|
@@ -183,7 +208,20 @@ With the `:json_api` adapter, the previous serializers would be rendered as:
|
|
|
183
208
|
{
|
|
184
209
|
"data": {
|
|
185
210
|
"id": "1",
|
|
186
|
-
"type": "profile"
|
|
211
|
+
"type": "profile",
|
|
212
|
+
"attributes": {
|
|
213
|
+
"name": "Julia"
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
With the `:json` adapter, the previous serializer would be rendered as:
|
|
220
|
+
|
|
221
|
+
``` json
|
|
222
|
+
{
|
|
223
|
+
"profile": {
|
|
224
|
+
"name": "Julia"
|
|
187
225
|
}
|
|
188
226
|
}
|
|
189
227
|
```
|
|
@@ -194,10 +232,19 @@ With the `:json_api` adapter, the previous serializers would be rendered as:
|
|
|
194
232
|
link :self do
|
|
195
233
|
href "https://example.com/link_author/#{object.id}"
|
|
196
234
|
end
|
|
197
|
-
link
|
|
198
|
-
link
|
|
235
|
+
link(:author) { link_author_url(object) }
|
|
236
|
+
link(:link_authors) { link_authors_url }
|
|
199
237
|
link :other, 'https://example.com/resource'
|
|
200
|
-
link
|
|
238
|
+
link(:posts) { link_author_posts_url(object) }
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Just like attributes, links also support conditions in options
|
|
242
|
+
```ruby
|
|
243
|
+
link(:secret, if: :internal?) { object.secret_link }
|
|
244
|
+
|
|
245
|
+
def internal?
|
|
246
|
+
instance_options[:context] == :internal
|
|
247
|
+
end
|
|
201
248
|
```
|
|
202
249
|
|
|
203
250
|
#### #object
|
|
@@ -206,7 +253,17 @@ The object being serialized.
|
|
|
206
253
|
|
|
207
254
|
#### #root
|
|
208
255
|
|
|
209
|
-
|
|
256
|
+
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.
|
|
257
|
+
By default, the resource root comes from the `model_name` of the serialized object's class.
|
|
258
|
+
|
|
259
|
+
There are several ways to specify root:
|
|
260
|
+
* [Overriding the root key](rendering.md#overriding-the-root-key)
|
|
261
|
+
* [Setting `type`](serializers.md#type)
|
|
262
|
+
* Specifying the `root` option, e.g. `root: 'specific_name'`, during the serializer's initialization:
|
|
263
|
+
|
|
264
|
+
```ruby
|
|
265
|
+
ActiveModelSerializers::SerializableResource.new(foo, root: 'bar')
|
|
266
|
+
```
|
|
210
267
|
|
|
211
268
|
#### #scope
|
|
212
269
|
|
|
@@ -249,13 +306,15 @@ end
|
|
|
249
306
|
Whether you write the method as above or as `object.comments.where(created_by: scope)`
|
|
250
307
|
is a matter of preference (assuming `scope_name` has been set).
|
|
251
308
|
|
|
309
|
+
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.
|
|
310
|
+
|
|
252
311
|
##### Controller Authorization Context
|
|
253
312
|
|
|
254
313
|
In the controller, the scope/scope_name options are equal to
|
|
255
314
|
the [`serialization_scope`method](https://github.com/rails-api/active_model_serializers/blob/d02cd30fe55a3ea85e1d351b6e039620903c1871/lib/action_controller/serialization.rb#L13-L20),
|
|
256
315
|
which is `:current_user`, by default.
|
|
257
316
|
|
|
258
|
-
|
|
317
|
+
Specifically, the `scope_name` is defaulted to `:current_user`, and may be set as
|
|
259
318
|
`serialization_scope :view_context`. The `scope` is set to `send(scope_name)` when `scope_name` is
|
|
260
319
|
present and the controller responds to `scope_name`.
|
|
261
320
|
|
|
@@ -266,7 +325,7 @@ current authorization scope when you call `render :json`.
|
|
|
266
325
|
called on every request. This was [also a problem](https://github.com/rails-api/active_model_serializers/pull/1252#issuecomment-159810477)
|
|
267
326
|
in [`0.9`](https://github.com/rails-api/active_model_serializers/tree/0-9-stable#customizing-scope).
|
|
268
327
|
|
|
269
|
-
We can change the scope from `current_user` to `view_context`.
|
|
328
|
+
We can change the scope from `current_user` to `view_context`, which is included in subclasses of `ActionController::Base`.
|
|
270
329
|
|
|
271
330
|
```diff
|
|
272
331
|
class SomeController < ActionController::Base
|
|
@@ -303,17 +362,65 @@ So that when we render the `#edit` action, we'll get
|
|
|
303
362
|
|
|
304
363
|
Where `can_edit` is `view_context.current_user.admin?` (true).
|
|
305
364
|
|
|
365
|
+
You can also tell what to set as `serialization_scope` for specific actions.
|
|
366
|
+
|
|
367
|
+
For example, use `admin_user` only for `Admin::PostSerializer` and `current_user` for rest.
|
|
368
|
+
|
|
369
|
+
```ruby
|
|
370
|
+
class PostsController < ActionController::Base
|
|
371
|
+
|
|
372
|
+
before_action only: :edit do
|
|
373
|
+
self.class.serialization_scope :admin_user
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
def show
|
|
377
|
+
render json: @post, serializer: PostSerializer
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
def edit
|
|
381
|
+
@post.save
|
|
382
|
+
render json: @post, serializer: Admin::PostSerializer
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
private
|
|
386
|
+
|
|
387
|
+
def admin_user
|
|
388
|
+
User.new(id: 2, name: 'Bob', admin: true)
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
def current_user
|
|
392
|
+
User.new(id: 2, name: 'Bob', admin: false)
|
|
393
|
+
end
|
|
394
|
+
end
|
|
395
|
+
```
|
|
396
|
+
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`.
|
|
397
|
+
|
|
306
398
|
#### #read_attribute_for_serialization(key)
|
|
307
399
|
|
|
308
400
|
The serialized value for a given key. e.g. `read_attribute_for_serialization(:title) #=> 'Hello World'`
|
|
309
401
|
|
|
310
402
|
#### #links
|
|
311
403
|
|
|
312
|
-
|
|
404
|
+
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.
|
|
405
|
+
|
|
406
|
+
```ruby
|
|
407
|
+
ActiveModelSerializers::SerializableResource.new(
|
|
408
|
+
@post,
|
|
409
|
+
adapter: :json_api,
|
|
410
|
+
links: {
|
|
411
|
+
self: {
|
|
412
|
+
href: 'http://example.com/posts',
|
|
413
|
+
meta: {
|
|
414
|
+
stuff: 'value'
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
)
|
|
419
|
+
```
|
|
313
420
|
|
|
314
421
|
#### #json_key
|
|
315
422
|
|
|
316
|
-
|
|
423
|
+
Returns the key used by the adapter as the resource root. See [root](#root) for more information.
|
|
317
424
|
|
|
318
425
|
## Examples
|
|
319
426
|
|
|
@@ -370,3 +477,19 @@ class PostSerializer < ActiveModel::Serializer
|
|
|
370
477
|
end
|
|
371
478
|
end
|
|
372
479
|
```
|
|
480
|
+
|
|
481
|
+
## Overriding association serializer lookup
|
|
482
|
+
|
|
483
|
+
If you want to define a specific serializer lookup for your associations, you can override
|
|
484
|
+
the `ActiveModel::Serializer.serializer_for` method to return a serializer class based on defined conditions.
|
|
485
|
+
|
|
486
|
+
```ruby
|
|
487
|
+
class MySerializer < ActiveModel::Serializer
|
|
488
|
+
def self.serializer_for(model, options)
|
|
489
|
+
return SparseAdminSerializer if model.class.name == 'Admin'
|
|
490
|
+
super
|
|
491
|
+
end
|
|
492
|
+
|
|
493
|
+
# the rest of the serializer
|
|
494
|
+
end
|
|
495
|
+
```
|
|
@@ -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.
|