active_model_serializers_custom 0.10.90
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 +7 -0
- data/.github/ISSUE_TEMPLATE.md +29 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +15 -0
- data/.gitignore +35 -0
- data/.rubocop.yml +109 -0
- data/.simplecov +110 -0
- data/.travis.yml +63 -0
- data/CHANGELOG.md +727 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/CONTRIBUTING.md +105 -0
- data/Gemfile +74 -0
- data/MIT-LICENSE +22 -0
- data/README.md +305 -0
- data/Rakefile +76 -0
- data/active_model_serializers.gemspec +64 -0
- data/appveyor.yml +28 -0
- data/bin/bench +171 -0
- data/bin/bench_regression +316 -0
- data/bin/rubocop +38 -0
- data/bin/serve_benchmark +39 -0
- data/docs/README.md +41 -0
- data/docs/STYLE.md +58 -0
- data/docs/general/adapters.md +269 -0
- data/docs/general/caching.md +58 -0
- data/docs/general/configuration_options.md +185 -0
- data/docs/general/deserialization.md +100 -0
- data/docs/general/fields.md +31 -0
- data/docs/general/getting_started.md +133 -0
- data/docs/general/instrumentation.md +40 -0
- data/docs/general/key_transforms.md +40 -0
- data/docs/general/logging.md +21 -0
- data/docs/general/rendering.md +293 -0
- data/docs/general/serializers.md +495 -0
- data/docs/how-open-source-maintained.jpg +0 -0
- data/docs/howto/add_pagination_links.md +138 -0
- data/docs/howto/add_relationship_links.md +140 -0
- data/docs/howto/add_root_key.md +62 -0
- data/docs/howto/grape_integration.md +42 -0
- data/docs/howto/outside_controller_use.md +66 -0
- data/docs/howto/passing_arbitrary_options.md +27 -0
- data/docs/howto/serialize_poro.md +73 -0
- data/docs/howto/test.md +154 -0
- data/docs/howto/upgrade_from_0_8_to_0_10.md +265 -0
- data/docs/integrations/ember-and-json-api.md +147 -0
- data/docs/integrations/grape.md +19 -0
- data/docs/jsonapi/errors.md +56 -0
- data/docs/jsonapi/schema.md +151 -0
- data/docs/jsonapi/schema/schema.json +366 -0
- data/docs/rfcs/0000-namespace.md +106 -0
- data/docs/rfcs/template.md +15 -0
- data/lib/action_controller/serialization.rb +76 -0
- data/lib/active_model/serializable_resource.rb +13 -0
- data/lib/active_model/serializer.rb +418 -0
- data/lib/active_model/serializer/adapter.rb +26 -0
- data/lib/active_model/serializer/adapter/attributes.rb +17 -0
- data/lib/active_model/serializer/adapter/base.rb +20 -0
- data/lib/active_model/serializer/adapter/json.rb +17 -0
- data/lib/active_model/serializer/adapter/json_api.rb +17 -0
- data/lib/active_model/serializer/adapter/null.rb +17 -0
- data/lib/active_model/serializer/array_serializer.rb +14 -0
- data/lib/active_model/serializer/association.rb +91 -0
- data/lib/active_model/serializer/attribute.rb +27 -0
- data/lib/active_model/serializer/belongs_to_reflection.rb +13 -0
- data/lib/active_model/serializer/collection_serializer.rb +90 -0
- data/lib/active_model/serializer/concerns/caching.rb +304 -0
- data/lib/active_model/serializer/error_serializer.rb +16 -0
- data/lib/active_model/serializer/errors_serializer.rb +34 -0
- data/lib/active_model/serializer/field.rb +92 -0
- data/lib/active_model/serializer/fieldset.rb +33 -0
- data/lib/active_model/serializer/has_many_reflection.rb +12 -0
- data/lib/active_model/serializer/has_one_reflection.rb +9 -0
- 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 +152 -0
- data/lib/active_model/serializer/null.rb +19 -0
- data/lib/active_model/serializer/reflection.rb +212 -0
- data/lib/active_model/serializer/version.rb +7 -0
- data/lib/active_model_serializers.rb +63 -0
- data/lib/active_model_serializers/adapter.rb +100 -0
- data/lib/active_model_serializers/adapter/attributes.rb +15 -0
- data/lib/active_model_serializers/adapter/base.rb +85 -0
- data/lib/active_model_serializers/adapter/json.rb +23 -0
- data/lib/active_model_serializers/adapter/json_api.rb +535 -0
- data/lib/active_model_serializers/adapter/json_api/deserialization.rb +215 -0
- data/lib/active_model_serializers/adapter/json_api/error.rb +98 -0
- data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +51 -0
- data/lib/active_model_serializers/adapter/json_api/link.rb +85 -0
- data/lib/active_model_serializers/adapter/json_api/meta.rb +39 -0
- data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +90 -0
- data/lib/active_model_serializers/adapter/json_api/relationship.rb +106 -0
- data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +68 -0
- data/lib/active_model_serializers/adapter/null.rb +11 -0
- data/lib/active_model_serializers/callbacks.rb +57 -0
- data/lib/active_model_serializers/deprecate.rb +56 -0
- data/lib/active_model_serializers/deserialization.rb +17 -0
- data/lib/active_model_serializers/json_pointer.rb +16 -0
- data/lib/active_model_serializers/logging.rb +124 -0
- data/lib/active_model_serializers/lookup_chain.rb +82 -0
- data/lib/active_model_serializers/model.rb +132 -0
- data/lib/active_model_serializers/railtie.rb +52 -0
- data/lib/active_model_serializers/register_jsonapi_renderer.rb +80 -0
- data/lib/active_model_serializers/serializable_resource.rb +84 -0
- data/lib/active_model_serializers/serialization_context.rb +41 -0
- data/lib/active_model_serializers/test.rb +9 -0
- data/lib/active_model_serializers/test/schema.rb +140 -0
- data/lib/active_model_serializers/test/serializer.rb +127 -0
- data/lib/generators/rails/USAGE +6 -0
- data/lib/generators/rails/resource_override.rb +12 -0
- data/lib/generators/rails/serializer_generator.rb +38 -0
- data/lib/generators/rails/templates/serializer.rb.erb +8 -0
- data/lib/grape/active_model_serializers.rb +18 -0
- data/lib/grape/formatters/active_model_serializers.rb +34 -0
- data/lib/grape/helpers/active_model_serializers.rb +19 -0
- data/lib/tasks/rubocop.rake +55 -0
- data/test/action_controller/adapter_selector_test.rb +64 -0
- data/test/action_controller/explicit_serializer_test.rb +137 -0
- data/test/action_controller/json/include_test.rb +248 -0
- data/test/action_controller/json_api/deserialization_test.rb +114 -0
- data/test/action_controller/json_api/errors_test.rb +42 -0
- data/test/action_controller/json_api/fields_test.rb +68 -0
- data/test/action_controller/json_api/linked_test.rb +204 -0
- data/test/action_controller/json_api/pagination_test.rb +126 -0
- data/test/action_controller/json_api/transform_test.rb +191 -0
- data/test/action_controller/lookup_proc_test.rb +51 -0
- data/test/action_controller/namespace_lookup_test.rb +239 -0
- data/test/action_controller/serialization_scope_name_test.rb +237 -0
- data/test/action_controller/serialization_test.rb +480 -0
- data/test/active_model_serializers/adapter_for_test.rb +210 -0
- data/test/active_model_serializers/json_pointer_test.rb +24 -0
- data/test/active_model_serializers/logging_test.rb +79 -0
- data/test/active_model_serializers/model_test.rb +144 -0
- data/test/active_model_serializers/railtie_test_isolated.rb +70 -0
- data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +163 -0
- data/test/active_model_serializers/serialization_context_test_isolated.rb +73 -0
- data/test/active_model_serializers/test/schema_test.rb +133 -0
- data/test/active_model_serializers/test/serializer_test.rb +64 -0
- data/test/active_record_test.rb +11 -0
- data/test/adapter/attributes_test.rb +42 -0
- data/test/adapter/deprecation_test.rb +102 -0
- data/test/adapter/json/belongs_to_test.rb +47 -0
- data/test/adapter/json/collection_test.rb +106 -0
- data/test/adapter/json/has_many_test.rb +55 -0
- data/test/adapter/json/transform_test.rb +95 -0
- data/test/adapter/json_api/belongs_to_test.rb +157 -0
- data/test/adapter/json_api/collection_test.rb +98 -0
- data/test/adapter/json_api/errors_test.rb +78 -0
- data/test/adapter/json_api/fields_test.rb +98 -0
- data/test/adapter/json_api/has_many_explicit_serializer_test.rb +98 -0
- data/test/adapter/json_api/has_many_test.rb +175 -0
- data/test/adapter/json_api/has_one_test.rb +82 -0
- data/test/adapter/json_api/include_data_if_sideloaded_test.rb +215 -0
- data/test/adapter/json_api/json_api_test.rb +35 -0
- data/test/adapter/json_api/linked_test.rb +415 -0
- data/test/adapter/json_api/links_test.rb +112 -0
- data/test/adapter/json_api/pagination_links_test.rb +208 -0
- data/test/adapter/json_api/parse_test.rb +139 -0
- data/test/adapter/json_api/relationship_test.rb +399 -0
- data/test/adapter/json_api/resource_meta_test.rb +102 -0
- data/test/adapter/json_api/toplevel_jsonapi_test.rb +84 -0
- data/test/adapter/json_api/transform_test.rb +514 -0
- data/test/adapter/json_api/type_test.rb +195 -0
- data/test/adapter/json_test.rb +48 -0
- data/test/adapter/null_test.rb +24 -0
- data/test/adapter/polymorphic_test.rb +220 -0
- data/test/adapter_test.rb +69 -0
- data/test/array_serializer_test.rb +24 -0
- data/test/benchmark/app.rb +67 -0
- data/test/benchmark/benchmarking_support.rb +69 -0
- data/test/benchmark/bm_active_record.rb +83 -0
- data/test/benchmark/bm_adapter.rb +40 -0
- data/test/benchmark/bm_caching.rb +121 -0
- data/test/benchmark/bm_lookup_chain.rb +85 -0
- data/test/benchmark/bm_transform.rb +47 -0
- data/test/benchmark/config.ru +3 -0
- data/test/benchmark/controllers.rb +85 -0
- data/test/benchmark/fixtures.rb +221 -0
- data/test/cache_test.rb +717 -0
- data/test/collection_serializer_test.rb +129 -0
- data/test/fixtures/active_record.rb +115 -0
- data/test/fixtures/poro.rb +227 -0
- data/test/generators/scaffold_controller_generator_test.rb +26 -0
- data/test/generators/serializer_generator_test.rb +77 -0
- data/test/grape_test.rb +198 -0
- data/test/lint_test.rb +51 -0
- data/test/logger_test.rb +22 -0
- data/test/poro_test.rb +11 -0
- data/test/serializable_resource_test.rb +81 -0
- data/test/serializers/association_macros_test.rb +39 -0
- data/test/serializers/associations_test.rb +520 -0
- data/test/serializers/attribute_test.rb +155 -0
- data/test/serializers/attributes_test.rb +54 -0
- data/test/serializers/caching_configuration_test_isolated.rb +172 -0
- data/test/serializers/configuration_test.rb +34 -0
- data/test/serializers/fieldset_test.rb +16 -0
- data/test/serializers/meta_test.rb +204 -0
- data/test/serializers/options_test.rb +34 -0
- data/test/serializers/read_attribute_for_serialization_test.rb +81 -0
- data/test/serializers/reflection_test.rb +481 -0
- data/test/serializers/root_test.rb +23 -0
- data/test/serializers/serialization_test.rb +57 -0
- data/test/serializers/serializer_for_test.rb +138 -0
- data/test/serializers/serializer_for_with_namespace_test.rb +90 -0
- data/test/support/custom_schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
- data/test/support/isolated_unit.rb +86 -0
- data/test/support/rails5_shims.rb +55 -0
- data/test/support/rails_app.rb +40 -0
- data/test/support/schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
- data/test/support/schemas/active_model_serializers/test/schema_test/my/show.json +6 -0
- data/test/support/schemas/custom/show.json +7 -0
- data/test/support/schemas/hyper_schema.json +93 -0
- data/test/support/schemas/render_using_json_api.json +43 -0
- data/test/support/schemas/simple_json_pointers.json +10 -0
- data/test/support/serialization_testing.rb +81 -0
- data/test/test_helper.rb +72 -0
- metadata +622 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
[Back to Guides](../README.md)
|
|
2
|
+
|
|
3
|
+
# Instrumentation
|
|
4
|
+
|
|
5
|
+
ActiveModelSerializers uses the
|
|
6
|
+
[ActiveSupport::Notification API](http://guides.rubyonrails.org/active_support_instrumentation.html#subscribing-to-an-event),
|
|
7
|
+
which allows for subscribing to events, such as for logging.
|
|
8
|
+
|
|
9
|
+
## Events
|
|
10
|
+
|
|
11
|
+
Name:
|
|
12
|
+
|
|
13
|
+
`render.active_model_serializers`
|
|
14
|
+
|
|
15
|
+
Payload (example):
|
|
16
|
+
|
|
17
|
+
```ruby
|
|
18
|
+
{
|
|
19
|
+
serializer: PostSerializer,
|
|
20
|
+
adapter: ActiveModelSerializers::Adapter::Attributes
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Subscribing:
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
ActiveSupport::Notifications.subscribe 'render.active_model_serializers' do |name, started, finished, unique_id, data|
|
|
28
|
+
# whatever
|
|
29
|
+
end
|
|
30
|
+
ActiveSupport::Notifications.subscribe 'render.active_model_serializers' do |*args|
|
|
31
|
+
event = ActiveSupport::Notifications::Event.new(*args)
|
|
32
|
+
# event.payload
|
|
33
|
+
# whatever
|
|
34
|
+
end
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## [LogSubscriber](http://api.rubyonrails.org/classes/ActiveSupport/LogSubscriber.html)
|
|
38
|
+
|
|
39
|
+
ActiveModelSerializers includes an `ActiveModelSerializers::LogSubscriber` that attaches to
|
|
40
|
+
`render.active_model_serializers`.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
[Back to Guides](../README.md)
|
|
2
|
+
|
|
3
|
+
# Key Transforms
|
|
4
|
+
|
|
5
|
+
Key Transforms modify the casing of keys and keys referenced in values in
|
|
6
|
+
serialized responses.
|
|
7
|
+
|
|
8
|
+
Provided key transforms:
|
|
9
|
+
|
|
10
|
+
| Option | Result |
|
|
11
|
+
|----|----|
|
|
12
|
+
| `:camel` | ExampleKey |
|
|
13
|
+
| `:camel_lower` | exampleKey |
|
|
14
|
+
| `:dash` | example-key |
|
|
15
|
+
| `:unaltered` | the original, unaltered key |
|
|
16
|
+
| `:underscore` | example_key |
|
|
17
|
+
| `nil` | use the adapter default |
|
|
18
|
+
|
|
19
|
+
Key translation precedence is as follows:
|
|
20
|
+
|
|
21
|
+
##### Adapter option
|
|
22
|
+
|
|
23
|
+
`key_transform` is provided as an option via render.
|
|
24
|
+
|
|
25
|
+
```render json: posts, each_serializer: PostSerializer, key_transform: :camel_lower```
|
|
26
|
+
|
|
27
|
+
##### Configuration option
|
|
28
|
+
|
|
29
|
+
`key_transform` is set in `ActiveModelSerializers.config.key_transform`.
|
|
30
|
+
|
|
31
|
+
```ActiveModelSerializers.config.key_transform = :camel_lower```
|
|
32
|
+
|
|
33
|
+
##### Adapter default
|
|
34
|
+
|
|
35
|
+
Each adapter has a default transform configured:
|
|
36
|
+
|
|
37
|
+
| Adapter | Default Key Transform |
|
|
38
|
+
|----|----|
|
|
39
|
+
| `Json` | `:unaltered` |
|
|
40
|
+
| `JsonApi` | `:dash` |
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
[Back to Guides](../README.md)
|
|
2
|
+
|
|
3
|
+
# Logging
|
|
4
|
+
|
|
5
|
+
The default logger in a Rails application will be `Rails.logger`.
|
|
6
|
+
|
|
7
|
+
When there is no `Rails.logger`, the default logger is an instance of
|
|
8
|
+
`ActiveSupport::TaggedLogging` logging to STDOUT.
|
|
9
|
+
|
|
10
|
+
You may customize the logger in an initializer, for example:
|
|
11
|
+
|
|
12
|
+
```ruby
|
|
13
|
+
ActiveModelSerializers.logger = Logger.new(STDOUT)
|
|
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
|
+
```
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
[Back to Guides](../README.md)
|
|
2
|
+
|
|
3
|
+
# Rendering
|
|
4
|
+
|
|
5
|
+
### Implicit Serializer
|
|
6
|
+
|
|
7
|
+
In your controllers, when you use `render :json`, Rails will now first search
|
|
8
|
+
for a serializer for the object and use it if available.
|
|
9
|
+
|
|
10
|
+
```ruby
|
|
11
|
+
class PostsController < ApplicationController
|
|
12
|
+
def show
|
|
13
|
+
@post = Post.find(params[:id])
|
|
14
|
+
|
|
15
|
+
render json: @post
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
In this case, Rails will look for a serializer named `PostSerializer`, and if
|
|
21
|
+
it exists, use it to serialize the `Post`.
|
|
22
|
+
|
|
23
|
+
### Explicit Serializer
|
|
24
|
+
|
|
25
|
+
If you wish to use a serializer other than the default, you can explicitly pass it to the renderer.
|
|
26
|
+
|
|
27
|
+
#### 1. For a resource:
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
render json: @post, serializer: PostPreviewSerializer
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
#### 2. For a resource collection:
|
|
34
|
+
|
|
35
|
+
Specify the serializer for each resource with `each_serializer`
|
|
36
|
+
|
|
37
|
+
```ruby
|
|
38
|
+
render json: @posts, each_serializer: PostPreviewSerializer
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The default serializer for collections is `CollectionSerializer`.
|
|
42
|
+
|
|
43
|
+
Specify the collection serializer with the `serializer` option.
|
|
44
|
+
|
|
45
|
+
```ruby
|
|
46
|
+
render json: @posts, serializer: CollectionSerializer, each_serializer: PostPreviewSerializer
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Serializing non-ActiveRecord objects
|
|
50
|
+
|
|
51
|
+
See [README](../../README.md#what-does-a-serializable-resource-look-like)
|
|
52
|
+
|
|
53
|
+
## SerializableResource options
|
|
54
|
+
|
|
55
|
+
See [README](../../README.md#activemodelserializersserializableresource)
|
|
56
|
+
|
|
57
|
+
### adapter_opts
|
|
58
|
+
|
|
59
|
+
#### fields
|
|
60
|
+
|
|
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.
|
|
67
|
+
|
|
68
|
+
#### adapter
|
|
69
|
+
|
|
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
|
+
```
|
|
75
|
+
|
|
76
|
+
#### key_transform
|
|
77
|
+
|
|
78
|
+
```render json: posts, each_serializer: PostSerializer, key_transform: :camel_lower```
|
|
79
|
+
|
|
80
|
+
See [Key Transforms](key_transforms.md) for more information.
|
|
81
|
+
|
|
82
|
+
#### meta
|
|
83
|
+
|
|
84
|
+
A `meta` member can be used to include non-standard meta-information. `meta` can
|
|
85
|
+
be utilized in several levels in a response.
|
|
86
|
+
|
|
87
|
+
##### Top-level
|
|
88
|
+
|
|
89
|
+
To set top-level `meta` in a response, specify it in the `render` call.
|
|
90
|
+
|
|
91
|
+
```ruby
|
|
92
|
+
render json: @post, meta: { total: 10 }
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The key can be customized using `meta_key` option.
|
|
96
|
+
|
|
97
|
+
```ruby
|
|
98
|
+
render json: @post, meta: { total: 10 }, meta_key: "custom_meta"
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
`meta` will only be included in your response if you are using an Adapter that
|
|
102
|
+
supports `root`, e.g., `JsonApi` and `Json` adapters. The default adapter,
|
|
103
|
+
`Attributes` does not have `root`.
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
##### Resource-level
|
|
107
|
+
|
|
108
|
+
To set resource-level `meta` in a response, define meta in a serializer with one
|
|
109
|
+
of the following methods:
|
|
110
|
+
|
|
111
|
+
As a single, static string.
|
|
112
|
+
|
|
113
|
+
```ruby
|
|
114
|
+
meta stuff: 'value'
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
As a block containing a Hash.
|
|
118
|
+
|
|
119
|
+
```ruby
|
|
120
|
+
meta do
|
|
121
|
+
{
|
|
122
|
+
rating: 4,
|
|
123
|
+
comments_count: object.comments.count
|
|
124
|
+
}
|
|
125
|
+
end
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
#### links
|
|
130
|
+
|
|
131
|
+
If you wish to use Rails url helpers for link generation, e.g., `link(:resources) { resources_url }`, ensure your application sets
|
|
132
|
+
`Rails.application.routes.default_url_options`.
|
|
133
|
+
|
|
134
|
+
##### Top-level
|
|
135
|
+
|
|
136
|
+
JsonApi supports a [links object](http://jsonapi.org/format/#document-links) to be specified at top-level, that you can specify in the `render`:
|
|
137
|
+
|
|
138
|
+
```ruby
|
|
139
|
+
links_object = {
|
|
140
|
+
href: "http://example.com/api/posts",
|
|
141
|
+
meta: {
|
|
142
|
+
count: 10
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
render json: @posts, links: links_object
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
That's the result:
|
|
149
|
+
|
|
150
|
+
```json
|
|
151
|
+
{
|
|
152
|
+
"data": [
|
|
153
|
+
{
|
|
154
|
+
"type": "posts",
|
|
155
|
+
"id": "1",
|
|
156
|
+
"attributes": {
|
|
157
|
+
"title": "JSON API is awesome!",
|
|
158
|
+
"body": "You should be using JSON API",
|
|
159
|
+
"created": "2015-05-22T14:56:29.000Z",
|
|
160
|
+
"updated": "2015-05-22T14:56:28.000Z"
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
],
|
|
164
|
+
"links": {
|
|
165
|
+
"href": "http://example.com/api/posts",
|
|
166
|
+
"meta": {
|
|
167
|
+
"count": 10
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
This feature is specific to JsonApi, so you have to use the use the [JsonApi Adapter](adapters.md#jsonapi)
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
##### Resource-level
|
|
177
|
+
|
|
178
|
+
In your serializer, define each link in one of the following methods:
|
|
179
|
+
|
|
180
|
+
As a static string
|
|
181
|
+
|
|
182
|
+
```ruby
|
|
183
|
+
link :link_name, 'https://example.com/resource'
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
As a block to be evaluated. When using Rails, URL helpers are available.
|
|
187
|
+
Ensure your application sets `Rails.application.routes.default_url_options`.
|
|
188
|
+
|
|
189
|
+
```ruby
|
|
190
|
+
link :link_name_ do
|
|
191
|
+
"https://example.com/resource/#{object.id}"
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
link(:link_name) { "https://example.com/resource/#{object.id}" }
|
|
195
|
+
|
|
196
|
+
link(:link_name) { resource_url(object) }
|
|
197
|
+
|
|
198
|
+
link(:link_name) { url_for(controller: 'controller_name', action: 'index', only_path: false) }
|
|
199
|
+
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### serializer_opts
|
|
203
|
+
|
|
204
|
+
#### include
|
|
205
|
+
|
|
206
|
+
See [Adapters: Include Option](/docs/general/adapters.md#include-option).
|
|
207
|
+
|
|
208
|
+
#### Overriding the root key
|
|
209
|
+
|
|
210
|
+
Overriding the resource root only applies when using the JSON adapter.
|
|
211
|
+
|
|
212
|
+
Normally, the resource root is derived from the class name of the resource being serialized.
|
|
213
|
+
e.g. `UserPostSerializer.new(UserPost.new)` will be serialized with the root `user_post` or `user_posts` according the adapter collection pluralization rules.
|
|
214
|
+
|
|
215
|
+
When using the JSON adapter in your initializer (ActiveModelSerializers.config.adapter = :json), or passing in the adapter in your render call, you can specify the root by passing it as an argument to `render`. For example:
|
|
216
|
+
|
|
217
|
+
```ruby
|
|
218
|
+
render json: @user_post, root: "admin_post", adapter: :json
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
This will be rendered as:
|
|
222
|
+
```json
|
|
223
|
+
{
|
|
224
|
+
"admin_post": {
|
|
225
|
+
"title": "how to do open source"
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
```
|
|
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.
|
|
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
|
+
|
|
261
|
+
#### serializer
|
|
262
|
+
|
|
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
|
+
```
|
|
278
|
+
|
|
279
|
+
#### scope
|
|
280
|
+
|
|
281
|
+
See [Serializers: Scope](/docs/general/serializers.md#scope).
|
|
282
|
+
|
|
283
|
+
#### scope_name
|
|
284
|
+
|
|
285
|
+
See [Serializers: Scope](/docs/general/serializers.md#scope).
|
|
286
|
+
|
|
287
|
+
## Using a serializer without `render`
|
|
288
|
+
|
|
289
|
+
See [Usage outside of a controller](../howto/outside_controller_use.md#serializing-before-controller-render).
|
|
290
|
+
|
|
291
|
+
## Pagination
|
|
292
|
+
|
|
293
|
+
See [How to add pagination links](../howto/add_pagination_links.md).
|
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
[Back to Guides](../README.md)
|
|
2
|
+
|
|
3
|
+
# Serializers
|
|
4
|
+
|
|
5
|
+
Given a serializer class:
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
class SomeSerializer < ActiveModel::Serializer
|
|
9
|
+
end
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
The following methods may be defined in it:
|
|
13
|
+
|
|
14
|
+
### Attributes
|
|
15
|
+
|
|
16
|
+
#### ::attributes
|
|
17
|
+
|
|
18
|
+
Serialization of the resource `title` and `body`
|
|
19
|
+
|
|
20
|
+
| In Serializer | #attributes |
|
|
21
|
+
|---------------------------- |-------------|
|
|
22
|
+
| `attributes :title, :body` | `{ title: 'Some Title', body: 'Some Body' }`
|
|
23
|
+
| `attributes :title, :body`<br>`def body "Special #{object.body}" end` | `{ title: 'Some Title', body: 'Special Some Body' }`
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
#### ::attribute
|
|
27
|
+
|
|
28
|
+
Serialization of the resource `title`
|
|
29
|
+
|
|
30
|
+
| In Serializer | #attributes |
|
|
31
|
+
|---------------------------- |-------------|
|
|
32
|
+
| `attribute :title` | `{ title: 'Some Title' } `
|
|
33
|
+
| `attribute :title, key: :name` | `{ name: 'Some Title' } `
|
|
34
|
+
| `attribute(:title) { 'A Different Title'}` | `{ title: 'A Different Title' } `
|
|
35
|
+
| `attribute :title`<br>`def title 'A Different Title' end` | `{ title: 'A Different Title' }`
|
|
36
|
+
|
|
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
|
+
```
|
|
49
|
+
|
|
50
|
+
### Associations
|
|
51
|
+
|
|
52
|
+
The interface for associations is, generically:
|
|
53
|
+
|
|
54
|
+
> `association_type(association_name, options, &block)`
|
|
55
|
+
|
|
56
|
+
Where:
|
|
57
|
+
|
|
58
|
+
- `association_type` may be `has_one`, `has_many`, `belongs_to`.
|
|
59
|
+
- `association_name` is a method name the serializer calls.
|
|
60
|
+
- optional: `options` may be:
|
|
61
|
+
- `key:` The name used for the serialized association.
|
|
62
|
+
- `serializer:`
|
|
63
|
+
- `if:`
|
|
64
|
+
- `unless:`
|
|
65
|
+
- `virtual_value:`
|
|
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.
|
|
71
|
+
- optional: `&block` is a context that returns the association's attributes.
|
|
72
|
+
- prevents `association_name` method from being called.
|
|
73
|
+
- return value of block is used as the association value.
|
|
74
|
+
- yields the `serializer` to the block.
|
|
75
|
+
- `include_data false` prevents the `data` key from being rendered in the JSON API relationship.
|
|
76
|
+
|
|
77
|
+
#### ::has_one
|
|
78
|
+
|
|
79
|
+
e.g.
|
|
80
|
+
|
|
81
|
+
```ruby
|
|
82
|
+
has_one :bio
|
|
83
|
+
has_one :blog, key: :site
|
|
84
|
+
has_one :blog, class_name: "Blog"
|
|
85
|
+
has_one :maker, virtual_value: { id: 1 }
|
|
86
|
+
|
|
87
|
+
has_one :blog do |serializer|
|
|
88
|
+
serializer.cached_blog
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def cached_blog
|
|
92
|
+
cache_store.fetch("cached_blog:#{object.updated_at}") do
|
|
93
|
+
Blog.find(object.blog_id)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
```ruby
|
|
99
|
+
has_one :blog, if: :show_blog?
|
|
100
|
+
# you can also use a string or lambda
|
|
101
|
+
# has_one :blog, if: 'scope.admin?'
|
|
102
|
+
# has_one :blog, if: -> (serializer) { serializer.scope.admin? }
|
|
103
|
+
# has_one :blog, if: -> { scope.admin? }
|
|
104
|
+
|
|
105
|
+
def show_blog?
|
|
106
|
+
scope.admin?
|
|
107
|
+
end
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
#### ::has_many
|
|
111
|
+
|
|
112
|
+
e.g.
|
|
113
|
+
|
|
114
|
+
```ruby
|
|
115
|
+
has_many :comments
|
|
116
|
+
has_many :comments, key: :reviews
|
|
117
|
+
has_many :comments, serializer: CommentPreviewSerializer
|
|
118
|
+
has_many :comments, class_name: "Comment"
|
|
119
|
+
has_many :reviews, virtual_value: [{ id: 1 }, { id: 2 }]
|
|
120
|
+
has_many :comments, key: :last_comments do
|
|
121
|
+
last(1)
|
|
122
|
+
end
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
#### ::belongs_to
|
|
126
|
+
|
|
127
|
+
e.g.
|
|
128
|
+
|
|
129
|
+
```ruby
|
|
130
|
+
belongs_to :author, serializer: AuthorPreviewSerializer
|
|
131
|
+
belongs_to :author, key: :writer
|
|
132
|
+
belongs_to :author, class_name: "Author"
|
|
133
|
+
belongs_to :post
|
|
134
|
+
belongs_to :blog
|
|
135
|
+
def blog
|
|
136
|
+
Blog.new(id: 999, name: 'Custom blog')
|
|
137
|
+
end
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Polymorphic Relationships
|
|
141
|
+
|
|
142
|
+
Polymorphic relationships are serialized by specifying the relationship, like any other association. For example:
|
|
143
|
+
|
|
144
|
+
```ruby
|
|
145
|
+
class PictureSerializer < ActiveModel::Serializer
|
|
146
|
+
has_one :imageable
|
|
147
|
+
end
|
|
148
|
+
```
|
|
149
|
+
|
|
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.
|
|
151
|
+
|
|
152
|
+
### Caching
|
|
153
|
+
|
|
154
|
+
#### ::cache
|
|
155
|
+
|
|
156
|
+
e.g.
|
|
157
|
+
|
|
158
|
+
```ruby
|
|
159
|
+
cache key: 'post', expires_in: 0.1, skip_digest: true
|
|
160
|
+
cache expires_in: 1.day, skip_digest: true
|
|
161
|
+
cache key: 'writer', skip_digest: true
|
|
162
|
+
cache only: [:name], skip_digest: true
|
|
163
|
+
cache except: [:content], skip_digest: true
|
|
164
|
+
cache key: 'blog'
|
|
165
|
+
cache only: [:id]
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
#### #cache_key
|
|
169
|
+
|
|
170
|
+
e.g.
|
|
171
|
+
|
|
172
|
+
```ruby
|
|
173
|
+
# Uses a custom non-time-based cache key
|
|
174
|
+
def cache_key
|
|
175
|
+
"#{self.class.name.downcase}/#{self.id}"
|
|
176
|
+
end
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Other
|
|
180
|
+
|
|
181
|
+
#### ::type
|
|
182
|
+
|
|
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
|
+
|
|
187
|
+
It either takes a `String` or `Symbol` as parameter.
|
|
188
|
+
|
|
189
|
+
Note: This method is useful only when using the `:json_api` or `:json` adapter.
|
|
190
|
+
|
|
191
|
+
Examples:
|
|
192
|
+
```ruby
|
|
193
|
+
class UserProfileSerializer < ActiveModel::Serializer
|
|
194
|
+
type 'profile'
|
|
195
|
+
|
|
196
|
+
attribute :name
|
|
197
|
+
end
|
|
198
|
+
class AuthorProfileSerializer < ActiveModel::Serializer
|
|
199
|
+
type :profile
|
|
200
|
+
|
|
201
|
+
attribute :name
|
|
202
|
+
end
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
With the `:json_api` adapter, the previous serializers would be rendered as:
|
|
206
|
+
|
|
207
|
+
``` json
|
|
208
|
+
{
|
|
209
|
+
"data": {
|
|
210
|
+
"id": "1",
|
|
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"
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
#### ::link
|
|
230
|
+
|
|
231
|
+
```ruby
|
|
232
|
+
link :self do
|
|
233
|
+
href "https://example.com/link_author/#{object.id}"
|
|
234
|
+
end
|
|
235
|
+
link(:author) { link_author_url(object) }
|
|
236
|
+
link(:link_authors) { link_authors_url }
|
|
237
|
+
link :other, 'https://example.com/resource'
|
|
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
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
#### #object
|
|
251
|
+
|
|
252
|
+
The object being serialized.
|
|
253
|
+
|
|
254
|
+
#### #root
|
|
255
|
+
|
|
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
|
+
```
|
|
267
|
+
|
|
268
|
+
#### #scope
|
|
269
|
+
|
|
270
|
+
Allows you to include in the serializer access to an external method.
|
|
271
|
+
|
|
272
|
+
It's intended to provide an authorization context to the serializer, so that
|
|
273
|
+
you may e.g. show an admin all comments on a post, else only published comments.
|
|
274
|
+
|
|
275
|
+
- `scope` is a method on the serializer instance that comes from `options[:scope]`. It may be nil.
|
|
276
|
+
- `scope_name` is an option passed to the new serializer (`options[:scope_name]`). The serializer
|
|
277
|
+
defines a method with that name that calls the `scope`, e.g. `def current_user; scope; end`.
|
|
278
|
+
Note: it does not define the method if the serializer instance responds to it.
|
|
279
|
+
|
|
280
|
+
That's a lot of words, so here's some examples:
|
|
281
|
+
|
|
282
|
+
First, let's assume the serializer is instantiated in the controller, since that's the usual scenario.
|
|
283
|
+
We'll refer to the serialization context as `controller`.
|
|
284
|
+
|
|
285
|
+
| options | `Serializer#scope` | method definition |
|
|
286
|
+
|-------- | ------------------|--------------------|
|
|
287
|
+
| `scope: current_user, scope_name: :current_user` | `current_user` | `Serializer#current_user` calls `controller.current_user`
|
|
288
|
+
| `scope: view_context, scope_name: :view_context` | `view_context` | `Serializer#view_context` calls `controller.view_context`
|
|
289
|
+
|
|
290
|
+
We can take advantage of the scope to customize the objects returned based
|
|
291
|
+
on the current user (scope).
|
|
292
|
+
|
|
293
|
+
For example, we can limit the posts the current user sees to those they created:
|
|
294
|
+
|
|
295
|
+
```ruby
|
|
296
|
+
class PostSerializer < ActiveModel::Serializer
|
|
297
|
+
attributes :id, :title, :body
|
|
298
|
+
|
|
299
|
+
# scope comments to those created_by the current user
|
|
300
|
+
has_many :comments do
|
|
301
|
+
object.comments.where(created_by: current_user)
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
Whether you write the method as above or as `object.comments.where(created_by: scope)`
|
|
307
|
+
is a matter of preference (assuming `scope_name` has been set).
|
|
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
|
+
|
|
311
|
+
##### Controller Authorization Context
|
|
312
|
+
|
|
313
|
+
In the controller, the scope/scope_name options are equal to
|
|
314
|
+
the [`serialization_scope`method](https://github.com/rails-api/active_model_serializers/blob/d02cd30fe55a3ea85e1d351b6e039620903c1871/lib/action_controller/serialization.rb#L13-L20),
|
|
315
|
+
which is `:current_user`, by default.
|
|
316
|
+
|
|
317
|
+
Specifically, the `scope_name` is defaulted to `:current_user`, and may be set as
|
|
318
|
+
`serialization_scope :view_context`. The `scope` is set to `send(scope_name)` when `scope_name` is
|
|
319
|
+
present and the controller responds to `scope_name`.
|
|
320
|
+
|
|
321
|
+
Thus, in a serializer, the controller provides `current_user` as the
|
|
322
|
+
current authorization scope when you call `render :json`.
|
|
323
|
+
|
|
324
|
+
**IMPORTANT**: Since the scope is set at render, you may want to customize it so that `current_user` isn't
|
|
325
|
+
called on every request. This was [also a problem](https://github.com/rails-api/active_model_serializers/pull/1252#issuecomment-159810477)
|
|
326
|
+
in [`0.9`](https://github.com/rails-api/active_model_serializers/tree/0-9-stable#customizing-scope).
|
|
327
|
+
|
|
328
|
+
We can change the scope from `current_user` to `view_context`, which is included in subclasses of `ActionController::Base`.
|
|
329
|
+
|
|
330
|
+
```diff
|
|
331
|
+
class SomeController < ActionController::Base
|
|
332
|
+
+ serialization_scope :view_context
|
|
333
|
+
|
|
334
|
+
def current_user
|
|
335
|
+
User.new(id: 2, name: 'Bob', admin: true)
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
def edit
|
|
339
|
+
user = User.new(id: 1, name: 'Pete')
|
|
340
|
+
render json: user, serializer: AdminUserSerializer, adapter: :json_api
|
|
341
|
+
end
|
|
342
|
+
end
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
We could then use the controller method `view_context` in our serializer, like so:
|
|
346
|
+
|
|
347
|
+
```diff
|
|
348
|
+
class AdminUserSerializer < ActiveModel::Serializer
|
|
349
|
+
attributes :id, :name, :can_edit
|
|
350
|
+
|
|
351
|
+
def can_edit?
|
|
352
|
+
+ view_context.current_user.admin?
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
So that when we render the `#edit` action, we'll get
|
|
358
|
+
|
|
359
|
+
```json
|
|
360
|
+
{"data":{"id":"1","type":"users","attributes":{"name":"Pete","can_edit":true}}}
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
Where `can_edit` is `view_context.current_user.admin?` (true).
|
|
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
|
+
|
|
398
|
+
#### #read_attribute_for_serialization(key)
|
|
399
|
+
|
|
400
|
+
The serialized value for a given key. e.g. `read_attribute_for_serialization(:title) #=> 'Hello World'`
|
|
401
|
+
|
|
402
|
+
#### #links
|
|
403
|
+
|
|
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
|
+
```
|
|
420
|
+
|
|
421
|
+
#### #json_key
|
|
422
|
+
|
|
423
|
+
Returns the key used by the adapter as the resource root. See [root](#root) for more information.
|
|
424
|
+
|
|
425
|
+
## Examples
|
|
426
|
+
|
|
427
|
+
Given two models, a `Post(title: string, body: text)` and a
|
|
428
|
+
`Comment(name: string, body: text, post_id: integer)`, you will have two
|
|
429
|
+
serializers:
|
|
430
|
+
|
|
431
|
+
```ruby
|
|
432
|
+
class PostSerializer < ActiveModel::Serializer
|
|
433
|
+
cache key: 'posts', expires_in: 3.hours
|
|
434
|
+
attributes :title, :body
|
|
435
|
+
|
|
436
|
+
has_many :comments
|
|
437
|
+
end
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
and
|
|
441
|
+
|
|
442
|
+
```ruby
|
|
443
|
+
class CommentSerializer < ActiveModel::Serializer
|
|
444
|
+
attributes :name, :body
|
|
445
|
+
|
|
446
|
+
belongs_to :post
|
|
447
|
+
end
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
Generally speaking, you, as a user of ActiveModelSerializers, will write (or generate) these
|
|
451
|
+
serializer classes.
|
|
452
|
+
|
|
453
|
+
## More Info
|
|
454
|
+
|
|
455
|
+
For more information, see [the Serializer class on GitHub](https://github.com/rails-api/active_model_serializers/blob/master/lib/active_model/serializer.rb)
|
|
456
|
+
|
|
457
|
+
## Overriding association methods
|
|
458
|
+
|
|
459
|
+
To override an association, call `has_many`, `has_one` or `belongs_to` with a block:
|
|
460
|
+
|
|
461
|
+
```ruby
|
|
462
|
+
class PostSerializer < ActiveModel::Serializer
|
|
463
|
+
has_many :comments do
|
|
464
|
+
object.comments.active
|
|
465
|
+
end
|
|
466
|
+
end
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
## Overriding attribute methods
|
|
470
|
+
|
|
471
|
+
To override an attribute, call `attribute` with a block:
|
|
472
|
+
|
|
473
|
+
```ruby
|
|
474
|
+
class PostSerializer < ActiveModel::Serializer
|
|
475
|
+
attribute :body do
|
|
476
|
+
object.body.downcase
|
|
477
|
+
end
|
|
478
|
+
end
|
|
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
|
+
```
|