active_model_serializers 0.10.3 → 0.10.12

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.
Files changed (224) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +154 -2
  3. data/README.md +153 -15
  4. data/lib/action_controller/serialization.rb +11 -1
  5. data/lib/active_model/serializable_resource.rb +2 -0
  6. data/lib/active_model/serializer.rb +275 -81
  7. data/lib/active_model/serializer/adapter.rb +2 -0
  8. data/lib/active_model/serializer/adapter/attributes.rb +2 -0
  9. data/lib/active_model/serializer/adapter/base.rb +2 -0
  10. data/lib/active_model/serializer/adapter/json.rb +2 -0
  11. data/lib/active_model/serializer/adapter/json_api.rb +2 -0
  12. data/lib/active_model/serializer/adapter/null.rb +2 -0
  13. data/lib/active_model/serializer/array_serializer.rb +2 -0
  14. data/lib/active_model/serializer/association.rb +53 -14
  15. data/lib/active_model/serializer/attribute.rb +2 -0
  16. data/lib/active_model/serializer/belongs_to_reflection.rb +7 -1
  17. data/lib/active_model/serializer/collection_serializer.rb +8 -5
  18. data/lib/active_model/serializer/concerns/caching.rb +36 -23
  19. data/lib/active_model/serializer/error_serializer.rb +2 -0
  20. data/lib/active_model/serializer/errors_serializer.rb +2 -0
  21. data/lib/active_model/serializer/field.rb +2 -0
  22. data/lib/active_model/serializer/fieldset.rb +3 -1
  23. data/lib/active_model/serializer/has_many_reflection.rb +6 -1
  24. data/lib/active_model/serializer/has_one_reflection.rb +3 -1
  25. data/lib/active_model/serializer/lazy_association.rb +99 -0
  26. data/lib/active_model/serializer/link.rb +23 -0
  27. data/lib/active_model/serializer/lint.rb +2 -0
  28. data/lib/active_model/serializer/null.rb +2 -0
  29. data/lib/active_model/serializer/reflection.rb +122 -73
  30. data/lib/active_model/serializer/version.rb +3 -1
  31. data/lib/active_model_serializers.rb +29 -11
  32. data/lib/active_model_serializers/adapter.rb +3 -1
  33. data/lib/active_model_serializers/adapter/attributes.rb +23 -0
  34. data/lib/active_model_serializers/adapter/base.rb +4 -2
  35. data/lib/active_model_serializers/adapter/json.rb +2 -0
  36. data/lib/active_model_serializers/adapter/json_api.rb +44 -26
  37. data/lib/active_model_serializers/adapter/json_api/deserialization.rb +4 -2
  38. data/lib/active_model_serializers/adapter/json_api/error.rb +2 -0
  39. data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +2 -0
  40. data/lib/active_model_serializers/adapter/json_api/link.rb +2 -0
  41. data/lib/active_model_serializers/adapter/json_api/meta.rb +2 -0
  42. data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +42 -21
  43. data/lib/active_model_serializers/adapter/json_api/relationship.rb +52 -9
  44. data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +35 -18
  45. data/lib/active_model_serializers/adapter/null.rb +2 -0
  46. data/lib/active_model_serializers/callbacks.rb +2 -0
  47. data/lib/active_model_serializers/deprecate.rb +2 -0
  48. data/lib/active_model_serializers/deserialization.rb +2 -0
  49. data/lib/active_model_serializers/json_pointer.rb +2 -0
  50. data/lib/active_model_serializers/logging.rb +2 -0
  51. data/lib/active_model_serializers/lookup_chain.rb +2 -0
  52. data/lib/active_model_serializers/model.rb +111 -30
  53. data/lib/active_model_serializers/model/caching.rb +25 -0
  54. data/lib/active_model_serializers/railtie.rb +4 -0
  55. data/lib/active_model_serializers/register_jsonapi_renderer.rb +2 -0
  56. data/lib/active_model_serializers/serializable_resource.rb +4 -2
  57. data/lib/active_model_serializers/serialization_context.rb +2 -0
  58. data/lib/active_model_serializers/test.rb +2 -0
  59. data/lib/active_model_serializers/test/schema.rb +4 -2
  60. data/lib/active_model_serializers/test/serializer.rb +2 -0
  61. data/lib/generators/rails/resource_override.rb +3 -1
  62. data/lib/generators/rails/serializer_generator.rb +2 -0
  63. data/lib/grape/active_model_serializers.rb +2 -0
  64. data/lib/grape/formatters/active_model_serializers.rb +2 -0
  65. data/lib/grape/helpers/active_model_serializers.rb +2 -0
  66. data/lib/tasks/rubocop.rake +55 -0
  67. metadata +74 -291
  68. data/.github/ISSUE_TEMPLATE.md +0 -29
  69. data/.github/PULL_REQUEST_TEMPLATE.md +0 -15
  70. data/.gitignore +0 -35
  71. data/.rubocop.yml +0 -102
  72. data/.simplecov +0 -110
  73. data/.travis.yml +0 -51
  74. data/CODE_OF_CONDUCT.md +0 -74
  75. data/CONTRIBUTING.md +0 -105
  76. data/Gemfile +0 -56
  77. data/Rakefile +0 -103
  78. data/active_model_serializers.gemspec +0 -62
  79. data/appveyor.yml +0 -24
  80. data/bin/bench +0 -171
  81. data/bin/bench_regression +0 -316
  82. data/bin/serve_benchmark +0 -39
  83. data/docs/ARCHITECTURE.md +0 -125
  84. data/docs/README.md +0 -42
  85. data/docs/STYLE.md +0 -58
  86. data/docs/general/adapters.md +0 -247
  87. data/docs/general/caching.md +0 -58
  88. data/docs/general/configuration_options.md +0 -169
  89. data/docs/general/deserialization.md +0 -100
  90. data/docs/general/fields.md +0 -31
  91. data/docs/general/getting_started.md +0 -133
  92. data/docs/general/instrumentation.md +0 -40
  93. data/docs/general/key_transforms.md +0 -40
  94. data/docs/general/logging.md +0 -14
  95. data/docs/general/rendering.md +0 -294
  96. data/docs/general/serializers.md +0 -461
  97. data/docs/how-open-source-maintained.jpg +0 -0
  98. data/docs/howto/add_pagination_links.md +0 -138
  99. data/docs/howto/add_relationship_links.md +0 -137
  100. data/docs/howto/add_root_key.md +0 -55
  101. data/docs/howto/grape_integration.md +0 -42
  102. data/docs/howto/outside_controller_use.md +0 -65
  103. data/docs/howto/passing_arbitrary_options.md +0 -27
  104. data/docs/howto/serialize_poro.md +0 -32
  105. data/docs/howto/test.md +0 -154
  106. data/docs/howto/upgrade_from_0_8_to_0_10.md +0 -265
  107. data/docs/integrations/ember-and-json-api.md +0 -144
  108. data/docs/integrations/grape.md +0 -19
  109. data/docs/jsonapi/errors.md +0 -56
  110. data/docs/jsonapi/schema.md +0 -151
  111. data/docs/jsonapi/schema/schema.json +0 -366
  112. data/docs/rfcs/0000-namespace.md +0 -106
  113. data/docs/rfcs/template.md +0 -15
  114. data/lib/active_model/serializer/collection_reflection.rb +0 -7
  115. data/lib/active_model/serializer/concerns/associations.rb +0 -102
  116. data/lib/active_model/serializer/concerns/attributes.rb +0 -82
  117. data/lib/active_model/serializer/concerns/configuration.rb +0 -59
  118. data/lib/active_model/serializer/concerns/links.rb +0 -35
  119. data/lib/active_model/serializer/concerns/meta.rb +0 -29
  120. data/lib/active_model/serializer/concerns/type.rb +0 -25
  121. data/lib/active_model/serializer/singular_reflection.rb +0 -7
  122. data/lib/active_model_serializers/key_transform.rb +0 -74
  123. data/test/action_controller/adapter_selector_test.rb +0 -53
  124. data/test/action_controller/explicit_serializer_test.rb +0 -135
  125. data/test/action_controller/json/include_test.rb +0 -246
  126. data/test/action_controller/json_api/deserialization_test.rb +0 -112
  127. data/test/action_controller/json_api/errors_test.rb +0 -40
  128. data/test/action_controller/json_api/fields_test.rb +0 -57
  129. data/test/action_controller/json_api/linked_test.rb +0 -202
  130. data/test/action_controller/json_api/pagination_test.rb +0 -116
  131. data/test/action_controller/json_api/transform_test.rb +0 -181
  132. data/test/action_controller/lookup_proc_test.rb +0 -49
  133. data/test/action_controller/namespace_lookup_test.rb +0 -226
  134. data/test/action_controller/serialization_scope_name_test.rb +0 -229
  135. data/test/action_controller/serialization_test.rb +0 -472
  136. data/test/active_model_serializers/adapter_for_test.rb +0 -208
  137. data/test/active_model_serializers/json_pointer_test.rb +0 -22
  138. data/test/active_model_serializers/key_transform_test.rb +0 -297
  139. data/test/active_model_serializers/logging_test.rb +0 -77
  140. data/test/active_model_serializers/model_test.rb +0 -22
  141. data/test/active_model_serializers/railtie_test_isolated.rb +0 -63
  142. data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +0 -143
  143. data/test/active_model_serializers/serialization_context_test_isolated.rb +0 -71
  144. data/test/active_model_serializers/test/schema_test.rb +0 -130
  145. data/test/active_model_serializers/test/serializer_test.rb +0 -62
  146. data/test/active_record_test.rb +0 -9
  147. data/test/adapter/attributes_test.rb +0 -43
  148. data/test/adapter/deprecation_test.rb +0 -100
  149. data/test/adapter/json/belongs_to_test.rb +0 -45
  150. data/test/adapter/json/collection_test.rb +0 -104
  151. data/test/adapter/json/has_many_test.rb +0 -45
  152. data/test/adapter/json/transform_test.rb +0 -93
  153. data/test/adapter/json_api/belongs_to_test.rb +0 -155
  154. data/test/adapter/json_api/collection_test.rb +0 -96
  155. data/test/adapter/json_api/errors_test.rb +0 -76
  156. data/test/adapter/json_api/fields_test.rb +0 -88
  157. data/test/adapter/json_api/has_many_embed_ids_test.rb +0 -43
  158. data/test/adapter/json_api/has_many_explicit_serializer_test.rb +0 -96
  159. data/test/adapter/json_api/has_many_test.rb +0 -165
  160. data/test/adapter/json_api/has_one_test.rb +0 -80
  161. data/test/adapter/json_api/include_data_if_sideloaded_test.rb +0 -166
  162. data/test/adapter/json_api/json_api_test.rb +0 -33
  163. data/test/adapter/json_api/linked_test.rb +0 -413
  164. data/test/adapter/json_api/links_test.rb +0 -95
  165. data/test/adapter/json_api/pagination_links_test.rb +0 -193
  166. data/test/adapter/json_api/parse_test.rb +0 -137
  167. data/test/adapter/json_api/relationship_test.rb +0 -397
  168. data/test/adapter/json_api/resource_identifier_test.rb +0 -110
  169. data/test/adapter/json_api/resource_meta_test.rb +0 -100
  170. data/test/adapter/json_api/toplevel_jsonapi_test.rb +0 -82
  171. data/test/adapter/json_api/transform_test.rb +0 -504
  172. data/test/adapter/json_api/type_test.rb +0 -61
  173. data/test/adapter/json_test.rb +0 -46
  174. data/test/adapter/null_test.rb +0 -22
  175. data/test/adapter/polymorphic_test.rb +0 -171
  176. data/test/adapter_test.rb +0 -67
  177. data/test/array_serializer_test.rb +0 -22
  178. data/test/benchmark/app.rb +0 -65
  179. data/test/benchmark/benchmarking_support.rb +0 -67
  180. data/test/benchmark/bm_active_record.rb +0 -81
  181. data/test/benchmark/bm_adapter.rb +0 -38
  182. data/test/benchmark/bm_caching.rb +0 -119
  183. data/test/benchmark/bm_lookup_chain.rb +0 -83
  184. data/test/benchmark/bm_transform.rb +0 -45
  185. data/test/benchmark/config.ru +0 -3
  186. data/test/benchmark/controllers.rb +0 -83
  187. data/test/benchmark/fixtures.rb +0 -219
  188. data/test/cache_test.rb +0 -579
  189. data/test/collection_serializer_test.rb +0 -110
  190. data/test/fixtures/active_record.rb +0 -78
  191. data/test/fixtures/poro.rb +0 -286
  192. data/test/generators/scaffold_controller_generator_test.rb +0 -24
  193. data/test/generators/serializer_generator_test.rb +0 -74
  194. data/test/grape_test.rb +0 -178
  195. data/test/lint_test.rb +0 -49
  196. data/test/logger_test.rb +0 -20
  197. data/test/poro_test.rb +0 -9
  198. data/test/serializable_resource_test.rb +0 -79
  199. data/test/serializers/association_macros_test.rb +0 -37
  200. data/test/serializers/associations_test.rb +0 -370
  201. data/test/serializers/attribute_test.rb +0 -151
  202. data/test/serializers/attributes_test.rb +0 -52
  203. data/test/serializers/caching_configuration_test_isolated.rb +0 -170
  204. data/test/serializers/configuration_test.rb +0 -32
  205. data/test/serializers/fieldset_test.rb +0 -14
  206. data/test/serializers/meta_test.rb +0 -202
  207. data/test/serializers/options_test.rb +0 -21
  208. data/test/serializers/read_attribute_for_serialization_test.rb +0 -79
  209. data/test/serializers/root_test.rb +0 -21
  210. data/test/serializers/serialization_test.rb +0 -55
  211. data/test/serializers/serializer_for_test.rb +0 -136
  212. data/test/serializers/serializer_for_with_namespace_test.rb +0 -87
  213. data/test/support/custom_schemas/active_model_serializers/test/schema_test/my/index.json +0 -6
  214. data/test/support/isolated_unit.rb +0 -82
  215. data/test/support/rails5_shims.rb +0 -53
  216. data/test/support/rails_app.rb +0 -36
  217. data/test/support/schemas/active_model_serializers/test/schema_test/my/index.json +0 -6
  218. data/test/support/schemas/active_model_serializers/test/schema_test/my/show.json +0 -6
  219. data/test/support/schemas/custom/show.json +0 -7
  220. data/test/support/schemas/hyper_schema.json +0 -93
  221. data/test/support/schemas/render_using_json_api.json +0 -43
  222. data/test/support/schemas/simple_json_pointers.json +0 -10
  223. data/test/support/serialization_testing.rb +0 -71
  224. data/test/test_helper.rb +0 -58
@@ -1,40 +0,0 @@
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`.
@@ -1,40 +0,0 @@
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` |
@@ -1,14 +0,0 @@
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
- ```
@@ -1,294 +0,0 @@
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
- All serializable resources must pass the
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).
56
-
57
- ## SerializableResource options
58
-
59
- The `options` hash passed to `render` or `ActiveModelSerializers::SerializableResource.new(resource, options)`
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.
71
-
72
- ### adapter_opts
73
-
74
- #### fields
75
-
76
- If you are using `json` or `attributes` adapter
77
- ```ruby
78
- render json: @user, fields: [:access_token]
79
- ```
80
-
81
- See [Fields](fields.md) for more information.
82
-
83
- #### adapter
84
-
85
- This option lets you explicitly set the adapter to be used by passing a registered adapter. Your options are `:attributes`, `:json`, and `:json_api`.
86
-
87
- ```
88
- ActiveModel::Serializer.config.adapter = :json_api
89
- ```
90
-
91
- #### key_transform
92
-
93
- ```render json: posts, each_serializer: PostSerializer, key_transform: :camel_lower```
94
-
95
- See [Key Transforms](key_transforms.md) for more information.
96
-
97
- #### meta
98
-
99
- A `meta` member can be used to include non-standard meta-information. `meta` can
100
- be utilized in several levels in a response.
101
-
102
- ##### Top-level
103
-
104
- To set top-level `meta` in a response, specify it in the `render` call.
105
-
106
- ```ruby
107
- render json: @post, meta: { total: 10 }
108
- ```
109
-
110
- The key can be customized using `meta_key` option.
111
-
112
- ```ruby
113
- render json: @post, meta: { total: 10 }, meta_key: "custom_meta"
114
- ```
115
-
116
- `meta` will only be included in your response if you are using an Adapter that
117
- supports `root`, e.g., `JsonApi` and `Json` adapters. The default adapter,
118
- `Attributes` does not have `root`.
119
-
120
-
121
- ##### Resource-level
122
-
123
- To set resource-level `meta` in a response, define meta in a serializer with one
124
- of the following methods:
125
-
126
- As a single, static string.
127
-
128
- ```ruby
129
- meta stuff: 'value'
130
- ```
131
-
132
- As a block containing a Hash.
133
-
134
- ```ruby
135
- meta do
136
- {
137
- rating: 4,
138
- comments_count: object.comments.count
139
- }
140
- end
141
- ```
142
-
143
-
144
- #### links
145
-
146
- If you wish to use Rails url helpers for link generation, e.g., `link(:resources) { resources_url }`, ensure your application sets
147
- `Rails.application.routes.default_url_options`.
148
-
149
- ##### Top-level
150
-
151
- JsonApi supports a [links object](http://jsonapi.org/format/#document-links) to be specified at top-level, that you can specify in the `render`:
152
-
153
- ```ruby
154
- links_object = {
155
- href: "http://example.com/api/posts",
156
- meta: {
157
- count: 10
158
- }
159
- }
160
- render json: @posts, links: links_object
161
- ```
162
-
163
- That's the result:
164
-
165
- ```json
166
- {
167
- "data": [
168
- {
169
- "type": "posts",
170
- "id": "1",
171
- "attributes": {
172
- "title": "JSON API is awesome!",
173
- "body": "You should be using JSON API",
174
- "created": "2015-05-22T14:56:29.000Z",
175
- "updated": "2015-05-22T14:56:28.000Z"
176
- }
177
- }
178
- ],
179
- "links": {
180
- "href": "http://example.com/api/posts",
181
- "meta": {
182
- "count": 10
183
- }
184
- }
185
- }
186
- ```
187
-
188
- This feature is specific to JsonApi, so you have to use the use the [JsonApi Adapter](adapters.md#jsonapi)
189
-
190
-
191
- ##### Resource-level
192
-
193
- In your serializer, define each link in one of the following methods:
194
-
195
- As a static string
196
-
197
- ```ruby
198
- link :link_name, 'https://example.com/resource'
199
- ```
200
-
201
- As a block to be evaluated. When using Rails, URL helpers are available.
202
- Ensure your application sets `Rails.application.routes.default_url_options`.
203
-
204
- ```ruby
205
- link :link_name_ do
206
- "https://example.com/resource/#{object.id}"
207
- end
208
-
209
- link(:link_name) { "https://example.com/resource/#{object.id}" }
210
-
211
- link(:link_name) { resource_url(object) }
212
-
213
- link(:link_name) { url_for(controller: 'controller_name', action: 'index', only_path: false) }
214
-
215
- ```
216
-
217
- ### serializer_opts
218
-
219
- #### include
220
-
221
- PR please :)
222
-
223
- #### Overriding the root key
224
-
225
- Overriding the resource root only applies when using the JSON adapter.
226
-
227
- Normally, the resource root is derived from the class name of the resource being serialized.
228
- e.g. `UserPostSerializer.new(UserPost.new)` will be serialized with the root `user_post` or `user_posts` according the adapter collection pluralization rules.
229
-
230
- 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:
231
-
232
- ```ruby
233
- render json: @user_post, root: "admin_post", adapter: :json
234
- ```
235
-
236
- This will be rendered as:
237
- ```json
238
- {
239
- "admin_post": {
240
- "title": "how to do open source"
241
- }
242
- }
243
- ```
244
- Note: the `Attributes` adapter (default) does not include a resource root. You also will not be able to create a single top-level root if you are using the :json_api adapter.
245
-
246
- #### namespace
247
-
248
- The namespace for serializer lookup is based on the controller.
249
-
250
- To configure the implicit namespace, in your controller, create a before filter
251
-
252
- ```ruby
253
- before_action do
254
- self.namespace_for_serializer = Api::V2
255
- end
256
- ```
257
-
258
- `namespace` can also be passed in as a render option:
259
-
260
-
261
- ```ruby
262
- @post = Post.first
263
- render json: @post, namespace: Api::V2
264
- ```
265
-
266
- This tells the serializer lookup to check for the existence of `Api::V2::PostSerializer`, and if any relations are rendered with `@post`, they will also utilize the `Api::V2` namespace.
267
-
268
- The `namespace` can be any object whose namespace can be represented by string interpolation (i.e. by calling to_s)
269
- - Module `Api::V2`
270
- - String `'Api::V2'`
271
- - Symbol `:'Api::V2'`
272
-
273
- Note that by using a string and symbol, Ruby will assume the namespace is defined at the top level.
274
-
275
-
276
- #### serializer
277
-
278
- PR please :)
279
-
280
- #### scope
281
-
282
- PR please :)
283
-
284
- #### scope_name
285
-
286
- PR please :)
287
-
288
- ## Using a serializer without `render`
289
-
290
- See [Usage outside of a controller](../howto/outside_controller_use.md#serializing-before-controller-render).
291
-
292
- ## Pagination
293
-
294
- See [How to add pagination links](https://github.com/rails-api/active_model_serializers/blob/master/docs/howto/add_pagination_links.md).
@@ -1,461 +0,0 @@
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
- - optional: `&block` is a context that returns the association's attributes.
68
- - prevents `association_name` method from being called.
69
- - return value of block is used as the association value.
70
- - yields the `serializer` to the block.
71
- - `include_data false` prevents the `data` key from being rendered in the JSON API relationship.
72
-
73
- #### ::has_one
74
-
75
- e.g.
76
-
77
- ```ruby
78
- has_one :bio
79
- has_one :blog, key: :site
80
- has_one :maker, virtual_value: { id: 1 }
81
-
82
- has_one :blog do |serializer|
83
- serializer.cached_blog
84
- end
85
-
86
- def cached_blog
87
- cache_store.fetch("cached_blog:#{object.updated_at}") do
88
- Blog.find(object.blog_id)
89
- end
90
- end
91
- ```
92
-
93
- ```ruby
94
- has_one :blog, if: :show_blog?
95
- # you can also use a string or lambda
96
- # has_one :blog, if: 'scope.admin?'
97
- # has_one :blog, if: -> (serializer) { serializer.scope.admin? }
98
- # has_one :blog, if: -> { scope.admin? }
99
-
100
- def show_blog?
101
- scope.admin?
102
- end
103
- ```
104
-
105
- #### ::has_many
106
-
107
- e.g.
108
-
109
- ```ruby
110
- has_many :comments
111
- has_many :comments, key: :reviews
112
- has_many :comments, serializer: CommentPreviewSerializer
113
- has_many :reviews, virtual_value: [{ id: 1 }, { id: 2 }]
114
- has_many :comments, key: :last_comments do
115
- last(1)
116
- end
117
- ```
118
-
119
- #### ::belongs_to
120
-
121
- e.g.
122
-
123
- ```ruby
124
- belongs_to :author, serializer: AuthorPreviewSerializer
125
- belongs_to :author, key: :writer
126
- belongs_to :post
127
- belongs_to :blog
128
- def blog
129
- Blog.new(id: 999, name: 'Custom blog')
130
- end
131
- ```
132
-
133
- ### Polymorphic Relationships
134
-
135
- Polymorphic relationships are serialized by specifying the relationship, like any other association. For example:
136
-
137
- ```ruby
138
- class PictureSerializer < ActiveModel::Serializer
139
- has_one :imageable
140
- end
141
- ```
142
-
143
- You can specify the serializers by [overriding serializer_for](serializers.md#overriding-association-serializer-lookup). For more context about polymorphic relationships, see the [tests](../../test/adapter/polymorphic_test.rb) for each adapter.
144
-
145
- ### Caching
146
-
147
- #### ::cache
148
-
149
- e.g.
150
-
151
- ```ruby
152
- cache key: 'post', expires_in: 0.1, skip_digest: true
153
- cache expires_in: 1.day, skip_digest: true
154
- cache key: 'writer', skip_digest: true
155
- cache only: [:name], skip_digest: true
156
- cache except: [:content], skip_digest: true
157
- cache key: 'blog'
158
- cache only: [:id]
159
- ```
160
-
161
- #### #cache_key
162
-
163
- e.g.
164
-
165
- ```ruby
166
- # Uses a custom non-time-based cache key
167
- def cache_key
168
- "#{self.class.name.downcase}/#{self.id}"
169
- end
170
- ```
171
-
172
- ### Other
173
-
174
- #### ::type
175
-
176
- When using the `:json_api` adapter, the `::type` method defines the JSONAPI [type](http://jsonapi.org/format/#document-resource-object-identification) that will be rendered for this serializer.
177
-
178
- When using the `:json` adapter, the `::type` method defines the name of the root element.
179
-
180
- It either takes a `String` or `Symbol` as parameter.
181
-
182
- Note: This method is useful only when using the `:json_api` or `:json` adapter.
183
-
184
- Examples:
185
- ```ruby
186
- class UserProfileSerializer < ActiveModel::Serializer
187
- type 'profile'
188
-
189
- attribute :name
190
- end
191
- class AuthorProfileSerializer < ActiveModel::Serializer
192
- type :profile
193
-
194
- attribute :name
195
- end
196
- ```
197
-
198
- With the `:json_api` adapter, the previous serializers would be rendered as:
199
-
200
- ``` json
201
- {
202
- "data": {
203
- "id": "1",
204
- "type": "profile",
205
- "attributes": {
206
- "name": "Julia"
207
- }
208
- }
209
- }
210
- ```
211
-
212
- With the `:json` adapter, the previous serializer would be rendered as:
213
-
214
- ``` json
215
- {
216
- "profile": {
217
- "name": "Julia"
218
- }
219
- }
220
- ```
221
-
222
- #### ::link
223
-
224
- ```ruby
225
- link :self do
226
- href "https://example.com/link_author/#{object.id}"
227
- end
228
- link :author { link_author_url(object) }
229
- link :link_authors { link_authors_url }
230
- link :other, 'https://example.com/resource'
231
- link :posts { link_author_posts_url(object) }
232
- ```
233
-
234
- #### #object
235
-
236
- The object being serialized.
237
-
238
- #### #root
239
-
240
- Resource root which is included in `JSON` adapter. As you can see at [Adapters Document](adapters.md), `Attribute` adapter (default) and `JSON API` adapter does not include root at top level.
241
- By default, the resource root comes from the `model_name` of the serialized object's class.
242
-
243
- There are several ways to specify root:
244
- * [Overriding the root key](rendering.md#overriding-the-root-key)
245
- * [Setting `type`](serializers.md#type)
246
- * Specifying the `root` option, e.g. `root: 'specific_name'`, during the serializer's initialization:
247
-
248
- ```ruby
249
- ActiveModelSerializers::SerializableResource.new(foo, root: 'bar')
250
- ```
251
-
252
- #### #scope
253
-
254
- Allows you to include in the serializer access to an external method.
255
-
256
- It's intended to provide an authorization context to the serializer, so that
257
- you may e.g. show an admin all comments on a post, else only published comments.
258
-
259
- - `scope` is a method on the serializer instance that comes from `options[:scope]`. It may be nil.
260
- - `scope_name` is an option passed to the new serializer (`options[:scope_name]`). The serializer
261
- defines a method with that name that calls the `scope`, e.g. `def current_user; scope; end`.
262
- Note: it does not define the method if the serializer instance responds to it.
263
-
264
- That's a lot of words, so here's some examples:
265
-
266
- First, let's assume the serializer is instantiated in the controller, since that's the usual scenario.
267
- We'll refer to the serialization context as `controller`.
268
-
269
- | options | `Serializer#scope` | method definition |
270
- |-------- | ------------------|--------------------|
271
- | `scope: current_user, scope_name: :current_user` | `current_user` | `Serializer#current_user` calls `controller.current_user`
272
- | `scope: view_context, scope_name: :view_context` | `view_context` | `Serializer#view_context` calls `controller.view_context`
273
-
274
- We can take advantage of the scope to customize the objects returned based
275
- on the current user (scope).
276
-
277
- For example, we can limit the posts the current user sees to those they created:
278
-
279
- ```ruby
280
- class PostSerializer < ActiveModel::Serializer
281
- attributes :id, :title, :body
282
-
283
- # scope comments to those created_by the current user
284
- has_many :comments do
285
- object.comments.where(created_by: current_user)
286
- end
287
- end
288
- ```
289
-
290
- Whether you write the method as above or as `object.comments.where(created_by: scope)`
291
- is a matter of preference (assuming `scope_name` has been set).
292
-
293
- ##### Controller Authorization Context
294
-
295
- In the controller, the scope/scope_name options are equal to
296
- the [`serialization_scope`method](https://github.com/rails-api/active_model_serializers/blob/d02cd30fe55a3ea85e1d351b6e039620903c1871/lib/action_controller/serialization.rb#L13-L20),
297
- which is `:current_user`, by default.
298
-
299
- Specifically, the `scope_name` is defaulted to `:current_user`, and may be set as
300
- `serialization_scope :view_context`. The `scope` is set to `send(scope_name)` when `scope_name` is
301
- present and the controller responds to `scope_name`.
302
-
303
- Thus, in a serializer, the controller provides `current_user` as the
304
- current authorization scope when you call `render :json`.
305
-
306
- **IMPORTANT**: Since the scope is set at render, you may want to customize it so that `current_user` isn't
307
- called on every request. This was [also a problem](https://github.com/rails-api/active_model_serializers/pull/1252#issuecomment-159810477)
308
- in [`0.9`](https://github.com/rails-api/active_model_serializers/tree/0-9-stable#customizing-scope).
309
-
310
- We can change the scope from `current_user` to `view_context`.
311
-
312
- ```diff
313
- class SomeController < ActionController::Base
314
- + serialization_scope :view_context
315
-
316
- def current_user
317
- User.new(id: 2, name: 'Bob', admin: true)
318
- end
319
-
320
- def edit
321
- user = User.new(id: 1, name: 'Pete')
322
- render json: user, serializer: AdminUserSerializer, adapter: :json_api
323
- end
324
- end
325
- ```
326
-
327
- We could then use the controller method `view_context` in our serializer, like so:
328
-
329
- ```diff
330
- class AdminUserSerializer < ActiveModel::Serializer
331
- attributes :id, :name, :can_edit
332
-
333
- def can_edit?
334
- + view_context.current_user.admin?
335
- end
336
- end
337
- ```
338
-
339
- So that when we render the `#edit` action, we'll get
340
-
341
- ```json
342
- {"data":{"id":"1","type":"users","attributes":{"name":"Pete","can_edit":true}}}
343
- ```
344
-
345
- Where `can_edit` is `view_context.current_user.admin?` (true).
346
-
347
- You can also tell what to set as `serialization_scope` for specific actions.
348
-
349
- For example, use `admin_user` only for `Admin::PostSerializer` and `current_user` for rest.
350
-
351
- ```ruby
352
- class PostsController < ActionController::Base
353
-
354
- before_action only: :edit do
355
- self.class.serialization_scope :admin_user
356
- end
357
-
358
- def show
359
- render json: @post, serializer: PostSerializer
360
- end
361
-
362
- def edit
363
- @post.save
364
- render json: @post, serializer: Admin::PostSerializer
365
- end
366
-
367
- private
368
-
369
- def admin_user
370
- User.new(id: 2, name: 'Bob', admin: true)
371
- end
372
-
373
- def current_user
374
- User.new(id: 2, name: 'Bob', admin: false)
375
- end
376
- end
377
- ```
378
-
379
- #### #read_attribute_for_serialization(key)
380
-
381
- The serialized value for a given key. e.g. `read_attribute_for_serialization(:title) #=> 'Hello World'`
382
-
383
- #### #links
384
-
385
- PR please :)
386
-
387
- #### #json_key
388
-
389
- PR please :)
390
-
391
- ## Examples
392
-
393
- Given two models, a `Post(title: string, body: text)` and a
394
- `Comment(name: string, body: text, post_id: integer)`, you will have two
395
- serializers:
396
-
397
- ```ruby
398
- class PostSerializer < ActiveModel::Serializer
399
- cache key: 'posts', expires_in: 3.hours
400
- attributes :title, :body
401
-
402
- has_many :comments
403
- end
404
- ```
405
-
406
- and
407
-
408
- ```ruby
409
- class CommentSerializer < ActiveModel::Serializer
410
- attributes :name, :body
411
-
412
- belongs_to :post
413
- end
414
- ```
415
-
416
- Generally speaking, you, as a user of ActiveModelSerializers, will write (or generate) these
417
- serializer classes.
418
-
419
- ## More Info
420
-
421
- For more information, see [the Serializer class on GitHub](https://github.com/rails-api/active_model_serializers/blob/master/lib/active_model/serializer.rb)
422
-
423
- ## Overriding association methods
424
-
425
- To override an association, call `has_many`, `has_one` or `belongs_to` with a block:
426
-
427
- ```ruby
428
- class PostSerializer < ActiveModel::Serializer
429
- has_many :comments do
430
- object.comments.active
431
- end
432
- end
433
- ```
434
-
435
- ## Overriding attribute methods
436
-
437
- To override an attribute, call `attribute` with a block:
438
-
439
- ```ruby
440
- class PostSerializer < ActiveModel::Serializer
441
- attribute :body do
442
- object.body.downcase
443
- end
444
- end
445
- ```
446
-
447
- ## Overriding association serializer lookup
448
-
449
- If you want to define a specific serializer lookup for your associations, you can override
450
- the `ActiveModel::Serializer.serializer_for` method to return a serializer class based on defined conditions.
451
-
452
- ```ruby
453
- class MySerializer < ActiveModel::Serializer
454
- def self.serializer_for(model, options)
455
- return SparseAdminSerializer if model.class == 'Admin'
456
- super
457
- end
458
-
459
- # the rest of the serializer
460
- end
461
- ```