active_model_serializers 0.10.0 → 0.10.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +6 -5
  3. data/.travis.yml +30 -21
  4. data/CHANGELOG.md +172 -2
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +23 -4
  7. data/README.md +166 -28
  8. data/Rakefile +3 -32
  9. data/active_model_serializers.gemspec +22 -25
  10. data/appveyor.yml +10 -6
  11. data/bin/rubocop +38 -0
  12. data/docs/README.md +2 -1
  13. data/docs/general/adapters.md +35 -11
  14. data/docs/general/caching.md +7 -1
  15. data/docs/general/configuration_options.md +86 -1
  16. data/docs/general/deserialization.md +1 -1
  17. data/docs/general/fields.md +31 -0
  18. data/docs/general/getting_started.md +1 -1
  19. data/docs/general/logging.md +7 -0
  20. data/docs/general/rendering.md +63 -25
  21. data/docs/general/serializers.md +125 -14
  22. data/docs/howto/add_pagination_links.md +16 -17
  23. data/docs/howto/add_relationship_links.md +140 -0
  24. data/docs/howto/add_root_key.md +11 -0
  25. data/docs/howto/grape_integration.md +42 -0
  26. data/docs/howto/outside_controller_use.md +12 -4
  27. data/docs/howto/passing_arbitrary_options.md +2 -2
  28. data/docs/howto/serialize_poro.md +46 -5
  29. data/docs/howto/test.md +2 -0
  30. data/docs/howto/upgrade_from_0_8_to_0_10.md +265 -0
  31. data/docs/integrations/ember-and-json-api.md +67 -32
  32. data/docs/jsonapi/schema.md +1 -1
  33. data/lib/action_controller/serialization.rb +13 -3
  34. data/lib/active_model/serializer/adapter/base.rb +2 -0
  35. data/lib/active_model/serializer/array_serializer.rb +8 -5
  36. data/lib/active_model/serializer/association.rb +62 -10
  37. data/lib/active_model/serializer/belongs_to_reflection.rb +4 -3
  38. data/lib/active_model/serializer/collection_serializer.rb +39 -13
  39. data/lib/active_model/serializer/{caching.rb → concerns/caching.rb} +82 -115
  40. data/lib/active_model/serializer/error_serializer.rb +11 -7
  41. data/lib/active_model/serializer/errors_serializer.rb +25 -20
  42. data/lib/active_model/serializer/has_many_reflection.rb +3 -3
  43. data/lib/active_model/serializer/has_one_reflection.rb +1 -4
  44. data/lib/active_model/serializer/lazy_association.rb +95 -0
  45. data/lib/active_model/serializer/lint.rb +134 -130
  46. data/lib/active_model/serializer/reflection.rb +127 -67
  47. data/lib/active_model/serializer/version.rb +1 -1
  48. data/lib/active_model/serializer.rb +297 -79
  49. data/lib/active_model_serializers/adapter/attributes.rb +3 -66
  50. data/lib/active_model_serializers/adapter/base.rb +39 -39
  51. data/lib/active_model_serializers/adapter/json_api/deserialization.rb +2 -2
  52. data/lib/active_model_serializers/adapter/json_api/link.rb +1 -1
  53. data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +47 -21
  54. data/lib/active_model_serializers/adapter/json_api/relationship.rb +75 -23
  55. data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +39 -10
  56. data/lib/active_model_serializers/adapter/json_api.rb +71 -57
  57. data/lib/active_model_serializers/adapter.rb +6 -0
  58. data/lib/active_model_serializers/deprecate.rb +1 -2
  59. data/lib/active_model_serializers/deserialization.rb +2 -0
  60. data/lib/active_model_serializers/lookup_chain.rb +80 -0
  61. data/lib/active_model_serializers/model.rb +109 -28
  62. data/lib/active_model_serializers/railtie.rb +3 -1
  63. data/lib/active_model_serializers/register_jsonapi_renderer.rb +44 -31
  64. data/lib/active_model_serializers/serializable_resource.rb +6 -5
  65. data/lib/active_model_serializers/serialization_context.rb +10 -3
  66. data/lib/active_model_serializers/test/schema.rb +2 -2
  67. data/lib/active_model_serializers.rb +16 -1
  68. data/lib/generators/rails/resource_override.rb +1 -1
  69. data/lib/generators/rails/serializer_generator.rb +4 -4
  70. data/lib/grape/active_model_serializers.rb +7 -5
  71. data/lib/grape/formatters/active_model_serializers.rb +19 -2
  72. data/lib/grape/helpers/active_model_serializers.rb +1 -0
  73. data/lib/tasks/rubocop.rake +53 -0
  74. data/test/action_controller/adapter_selector_test.rb +14 -5
  75. data/test/action_controller/explicit_serializer_test.rb +5 -4
  76. data/test/action_controller/json/include_test.rb +106 -27
  77. data/test/action_controller/json_api/deserialization_test.rb +1 -1
  78. data/test/action_controller/json_api/errors_test.rb +8 -9
  79. data/test/action_controller/json_api/fields_test.rb +66 -0
  80. data/test/action_controller/json_api/linked_test.rb +29 -24
  81. data/test/action_controller/json_api/pagination_test.rb +31 -23
  82. data/test/action_controller/json_api/transform_test.rb +11 -3
  83. data/test/action_controller/lookup_proc_test.rb +49 -0
  84. data/test/action_controller/namespace_lookup_test.rb +232 -0
  85. data/test/action_controller/serialization_scope_name_test.rb +12 -6
  86. data/test/action_controller/serialization_test.rb +12 -9
  87. data/test/active_model_serializers/json_pointer_test.rb +15 -13
  88. data/test/active_model_serializers/model_test.rb +137 -4
  89. data/test/active_model_serializers/railtie_test_isolated.rb +12 -7
  90. data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +161 -0
  91. data/test/active_model_serializers/serialization_context_test_isolated.rb +23 -10
  92. data/test/active_model_serializers/test/schema_test.rb +3 -2
  93. data/test/adapter/attributes_test.rb +40 -0
  94. data/test/adapter/json/collection_test.rb +14 -0
  95. data/test/adapter/json/has_many_test.rb +10 -2
  96. data/test/adapter/json/transform_test.rb +15 -15
  97. data/test/adapter/json_api/collection_test.rb +4 -3
  98. data/test/adapter/json_api/errors_test.rb +17 -19
  99. data/test/adapter/json_api/fields_test.rb +12 -3
  100. data/test/adapter/json_api/has_many_test.rb +49 -20
  101. data/test/adapter/json_api/include_data_if_sideloaded_test.rb +213 -0
  102. data/test/adapter/json_api/json_api_test.rb +5 -7
  103. data/test/adapter/json_api/linked_test.rb +33 -12
  104. data/test/adapter/json_api/links_test.rb +4 -2
  105. data/test/adapter/json_api/pagination_links_test.rb +53 -13
  106. data/test/adapter/json_api/parse_test.rb +1 -1
  107. data/test/adapter/json_api/relationship_test.rb +309 -73
  108. data/test/adapter/json_api/resource_meta_test.rb +3 -3
  109. data/test/adapter/json_api/transform_test.rb +263 -253
  110. data/test/adapter/json_api/type_test.rb +168 -36
  111. data/test/adapter/json_test.rb +8 -7
  112. data/test/adapter/null_test.rb +1 -2
  113. data/test/adapter/polymorphic_test.rb +52 -5
  114. data/test/adapter_test.rb +1 -1
  115. data/test/benchmark/app.rb +1 -1
  116. data/test/benchmark/benchmarking_support.rb +1 -1
  117. data/test/benchmark/bm_active_record.rb +81 -0
  118. data/test/benchmark/bm_adapter.rb +38 -0
  119. data/test/benchmark/bm_caching.rb +16 -16
  120. data/test/benchmark/bm_lookup_chain.rb +83 -0
  121. data/test/benchmark/bm_transform.rb +21 -10
  122. data/test/benchmark/controllers.rb +16 -17
  123. data/test/benchmark/fixtures.rb +72 -72
  124. data/test/cache_test.rb +235 -69
  125. data/test/collection_serializer_test.rb +31 -14
  126. data/test/fixtures/active_record.rb +45 -10
  127. data/test/fixtures/poro.rb +124 -181
  128. data/test/generators/serializer_generator_test.rb +23 -5
  129. data/test/grape_test.rb +170 -56
  130. data/test/lint_test.rb +1 -1
  131. data/test/logger_test.rb +13 -11
  132. data/test/serializable_resource_test.rb +18 -22
  133. data/test/serializers/association_macros_test.rb +3 -2
  134. data/test/serializers/associations_test.rb +222 -49
  135. data/test/serializers/attribute_test.rb +5 -3
  136. data/test/serializers/attributes_test.rb +1 -1
  137. data/test/serializers/caching_configuration_test_isolated.rb +6 -6
  138. data/test/serializers/fieldset_test.rb +1 -1
  139. data/test/serializers/meta_test.rb +12 -6
  140. data/test/serializers/options_test.rb +17 -6
  141. data/test/serializers/read_attribute_for_serialization_test.rb +3 -3
  142. data/test/serializers/reflection_test.rb +427 -0
  143. data/test/serializers/root_test.rb +1 -1
  144. data/test/serializers/serialization_test.rb +2 -2
  145. data/test/serializers/serializer_for_test.rb +12 -10
  146. data/test/serializers/serializer_for_with_namespace_test.rb +88 -0
  147. data/test/support/isolated_unit.rb +9 -4
  148. data/test/support/rails5_shims.rb +8 -2
  149. data/test/support/rails_app.rb +2 -9
  150. data/test/support/serialization_testing.rb +31 -5
  151. data/test/test_helper.rb +13 -0
  152. metadata +130 -71
  153. data/.rubocop_todo.yml +0 -167
  154. data/docs/ARCHITECTURE.md +0 -126
  155. data/lib/active_model/serializer/associations.rb +0 -100
  156. data/lib/active_model/serializer/attributes.rb +0 -82
  157. data/lib/active_model/serializer/collection_reflection.rb +0 -7
  158. data/lib/active_model/serializer/configuration.rb +0 -35
  159. data/lib/active_model/serializer/include_tree.rb +0 -111
  160. data/lib/active_model/serializer/links.rb +0 -35
  161. data/lib/active_model/serializer/meta.rb +0 -29
  162. data/lib/active_model/serializer/singular_reflection.rb +0 -7
  163. data/lib/active_model/serializer/type.rb +0 -25
  164. data/lib/active_model_serializers/key_transform.rb +0 -70
  165. data/test/active_model_serializers/key_transform_test.rb +0 -263
  166. data/test/adapter/json_api/has_many_embed_ids_test.rb +0 -43
  167. data/test/adapter/json_api/relationships_test.rb +0 -199
  168. data/test/adapter/json_api/resource_identifier_test.rb +0 -85
  169. data/test/include_tree/from_include_args_test.rb +0 -26
  170. data/test/include_tree/from_string_test.rb +0 -94
  171. 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
- ## JSON API
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
 
@@ -42,7 +42,7 @@ document = {
42
42
  'title' => 'Title 1',
43
43
  'date' => '2015-12-20'
44
44
  },
45
- 'associations' => {
45
+ 'relationships' => {
46
46
  'author' => {
47
47
  'data' => {
48
48
  'type' => 'user',
@@ -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.
@@ -37,7 +37,7 @@ and
37
37
  class CommentSerializer < ActiveModel::Serializer
38
38
  attributes :name, :body
39
39
 
40
- belongs_to :post_id
40
+ belongs_to :post
41
41
  end
42
42
  ```
43
43
 
@@ -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
+ ```
@@ -48,42 +48,36 @@ render json: @posts, serializer: CollectionSerializer, each_serializer: PostPrev
48
48
 
49
49
  ## Serializing non-ActiveRecord objects
50
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).
51
+ See [README](../../README.md#what-does-a-serializable-resource-look-like)
56
52
 
57
53
  ## SerializableResource options
58
54
 
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.
55
+ See [README](../../README.md#activemodelserializersserializableresource)
71
56
 
72
57
  ### adapter_opts
73
58
 
74
59
  #### fields
75
60
 
76
- PR please :)
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
- PR please :)
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 informaiton.
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
- PR please :)
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
- PR please :)
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
- PR please :)
281
+ See [Serializers: Scope](/docs/general/serializers.md#scope).
244
282
 
245
283
  #### scope_name
246
284
 
247
- PR please :)
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](https://github.com/rails-api/active_model_serializers/blob/master/docs/howto/add_pagination_links.md).
293
+ See [How to add pagination links](../howto/add_pagination_links.md).
@@ -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 :title { 'A Different Title'}` | `{ title: 'A Different Title' } `
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
- [PR please for conditional attributes:)](https://github.com/rails-api/active_model_serializers/pull/1403)
37
+ An `if` or `unless` option can make an attribute conditional. It takes a symbol of a method name on the serializer, or a lambda literal.
38
+
39
+ e.g.
40
+
41
+ ```ruby
42
+ attribute :private_data, if: :is_current_user?
43
+ attribute :another_private_data, if: -> { scope.admin? }
44
+
45
+ def is_current_user?
46
+ object.id == current_user.id
47
+ end
48
+ ```
38
49
 
39
50
  ### Associations
40
51
 
@@ -53,6 +64,10 @@ Where:
53
64
  - `unless:`
54
65
  - `virtual_value:`
55
66
  - `polymorphic:` defines if polymorphic relation type should be nested in serialized association.
67
+ - `type:` the resource type as used by JSON:API, especially on a `belongs_to` relationship.
68
+ - `class_name:` used to determine `type` when `type` not given
69
+ - `foreign_key:` used by JSON:API on a `belongs_to` relationship to avoid unnecessarily loading the association object.
70
+ - `namespace:` used when looking up the serializer and `serializer` is not given. Falls back to the parent serializer's `:namespace` instance options, which, when present, comes from the render options. See [Rendering#namespace](rendering.md#namespace] for more details.
56
71
  - optional: `&block` is a context that returns the association's attributes.
57
72
  - prevents `association_name` method from being called.
58
73
  - return value of block is used as the association value.
@@ -129,7 +144,7 @@ class PictureSerializer < ActiveModel::Serializer
129
144
  end
130
145
  ```
131
146
 
132
- For more context, see the [tests](../../test/adapter/polymorphic_test.rb) for each adapter.
147
+ You can specify the serializers by [overriding serializer_for](serializers.md#overriding-association-serializer-lookup). For more context about polymorphic relationships, see the [tests](../../test/adapter/polymorphic_test.rb) for each adapter.
133
148
 
134
149
  ### Caching
135
150
 
@@ -162,18 +177,25 @@ end
162
177
 
163
178
  #### ::type
164
179
 
165
- The `::type` method defines the JSONAPI [type](http://jsonapi.org/format/#document-resource-object-identification) that will be rendered for this serializer.
180
+ When using the `:json_api` adapter, the `::type` method defines the JSONAPI [type](http://jsonapi.org/format/#document-resource-object-identification) that will be rendered for this serializer.
181
+
182
+ When using the `:json` adapter, the `::type` method defines the name of the root element.
183
+
166
184
  It either takes a `String` or `Symbol` as parameter.
167
185
 
168
- Note: This method is useful only when using the `:json_api` adapter.
186
+ Note: This method is useful only when using the `:json_api` or `:json` adapter.
169
187
 
170
188
  Examples:
171
189
  ```ruby
172
190
  class UserProfileSerializer < ActiveModel::Serializer
173
191
  type 'profile'
192
+
193
+ attribute :name
174
194
  end
175
195
  class AuthorProfileSerializer < ActiveModel::Serializer
176
196
  type :profile
197
+
198
+ attribute :name
177
199
  end
178
200
  ```
179
201
 
@@ -183,7 +205,20 @@ With the `:json_api` adapter, the previous serializers would be rendered as:
183
205
  {
184
206
  "data": {
185
207
  "id": "1",
186
- "type": "profile"
208
+ "type": "profile",
209
+ "attributes": {
210
+ "name": "Julia"
211
+ }
212
+ }
213
+ }
214
+ ```
215
+
216
+ With the `:json` adapter, the previous serializer would be rendered as:
217
+
218
+ ``` json
219
+ {
220
+ "profile": {
221
+ "name": "Julia"
187
222
  }
188
223
  }
189
224
  ```
@@ -194,10 +229,10 @@ With the `:json_api` adapter, the previous serializers would be rendered as:
194
229
  link :self do
195
230
  href "https://example.com/link_author/#{object.id}"
196
231
  end
197
- link :author { link_author_url(object) }
198
- link :link_authors { link_authors_url }
232
+ link(:author) { link_author_url(object) }
233
+ link(:link_authors) { link_authors_url }
199
234
  link :other, 'https://example.com/resource'
200
- link :posts { link_author_posts_url(object) }
235
+ link(:posts) { link_author_posts_url(object) }
201
236
  ```
202
237
 
203
238
  #### #object
@@ -206,7 +241,17 @@ The object being serialized.
206
241
 
207
242
  #### #root
208
243
 
209
- PR please :)
244
+ Resource root which is included in `JSON` adapter. As you can see at [Adapters Document](adapters.md), `Attribute` adapter (default) and `JSON API` adapter does not include root at top level.
245
+ By default, the resource root comes from the `model_name` of the serialized object's class.
246
+
247
+ There are several ways to specify root:
248
+ * [Overriding the root key](rendering.md#overriding-the-root-key)
249
+ * [Setting `type`](serializers.md#type)
250
+ * Specifying the `root` option, e.g. `root: 'specific_name'`, during the serializer's initialization:
251
+
252
+ ```ruby
253
+ ActiveModelSerializers::SerializableResource.new(foo, root: 'bar')
254
+ ```
210
255
 
211
256
  #### #scope
212
257
 
@@ -249,13 +294,15 @@ end
249
294
  Whether you write the method as above or as `object.comments.where(created_by: scope)`
250
295
  is a matter of preference (assuming `scope_name` has been set).
251
296
 
297
+ Keep in mind that the scope can be set to any available controller reference. This can be utilized to provide access to any other data scopes or presentation helpers.
298
+
252
299
  ##### Controller Authorization Context
253
300
 
254
301
  In the controller, the scope/scope_name options are equal to
255
302
  the [`serialization_scope`method](https://github.com/rails-api/active_model_serializers/blob/d02cd30fe55a3ea85e1d351b6e039620903c1871/lib/action_controller/serialization.rb#L13-L20),
256
303
  which is `:current_user`, by default.
257
304
 
258
- Specfically, the `scope_name` is defaulted to `:current_user`, and may be set as
305
+ Specifically, the `scope_name` is defaulted to `:current_user`, and may be set as
259
306
  `serialization_scope :view_context`. The `scope` is set to `send(scope_name)` when `scope_name` is
260
307
  present and the controller responds to `scope_name`.
261
308
 
@@ -266,7 +313,7 @@ current authorization scope when you call `render :json`.
266
313
  called on every request. This was [also a problem](https://github.com/rails-api/active_model_serializers/pull/1252#issuecomment-159810477)
267
314
  in [`0.9`](https://github.com/rails-api/active_model_serializers/tree/0-9-stable#customizing-scope).
268
315
 
269
- We can change the scope from `current_user` to `view_context`.
316
+ We can change the scope from `current_user` to `view_context`, which is included in subclasses of `ActionController::Base`.
270
317
 
271
318
  ```diff
272
319
  class SomeController < ActionController::Base
@@ -303,17 +350,65 @@ So that when we render the `#edit` action, we'll get
303
350
 
304
351
  Where `can_edit` is `view_context.current_user.admin?` (true).
305
352
 
353
+ You can also tell what to set as `serialization_scope` for specific actions.
354
+
355
+ For example, use `admin_user` only for `Admin::PostSerializer` and `current_user` for rest.
356
+
357
+ ```ruby
358
+ class PostsController < ActionController::Base
359
+
360
+ before_action only: :edit do
361
+ self.class.serialization_scope :admin_user
362
+ end
363
+
364
+ def show
365
+ render json: @post, serializer: PostSerializer
366
+ end
367
+
368
+ def edit
369
+ @post.save
370
+ render json: @post, serializer: Admin::PostSerializer
371
+ end
372
+
373
+ private
374
+
375
+ def admin_user
376
+ User.new(id: 2, name: 'Bob', admin: true)
377
+ end
378
+
379
+ def current_user
380
+ User.new(id: 2, name: 'Bob', admin: false)
381
+ end
382
+ end
383
+ ```
384
+ Note that any controller reference which provides the desired scope is acceptable, such as another controller method for loading a different resource or reference to helpers. For example, `ActionController::API` does not include `ActionView::ViewContext`, and would need a different reference for passing any helpers into a serializer via `serialization_scope`.
385
+
306
386
  #### #read_attribute_for_serialization(key)
307
387
 
308
388
  The serialized value for a given key. e.g. `read_attribute_for_serialization(:title) #=> 'Hello World'`
309
389
 
310
390
  #### #links
311
391
 
312
- PR please :)
392
+ Allows you to modify the `links` node. By default, this node will be populated with the attributes set using the [::link](#link) method. Using `links: nil` will remove the `links` node.
393
+
394
+ ```ruby
395
+ ActiveModelSerializers::SerializableResource.new(
396
+ @post,
397
+ adapter: :json_api,
398
+ links: {
399
+ self: {
400
+ href: 'http://example.com/posts',
401
+ meta: {
402
+ stuff: 'value'
403
+ }
404
+ }
405
+ }
406
+ )
407
+ ```
313
408
 
314
409
  #### #json_key
315
410
 
316
- PR please :)
411
+ Returns the key used by the adapter as the resource root. See [root](#root) for more information.
317
412
 
318
413
  ## Examples
319
414
 
@@ -370,3 +465,19 @@ class PostSerializer < ActiveModel::Serializer
370
465
  end
371
466
  end
372
467
  ```
468
+
469
+ ## Overriding association serializer lookup
470
+
471
+ If you want to define a specific serializer lookup for your associations, you can override
472
+ the `ActiveModel::Serializer.serializer_for` method to return a serializer class based on defined conditions.
473
+
474
+ ```ruby
475
+ class MySerializer < ActiveModel::Serializer
476
+ def self.serializer_for(model, options)
477
+ return SparseAdminSerializer if model.class == 'Admin'
478
+ super
479
+ end
480
+
481
+ # the rest of the serializer
482
+ end
483
+ ```
@@ -10,9 +10,9 @@ the resource is paginated and if you are using the ```JsonApi``` adapter.
10
10
  If you want pagination links in your response, use [Kaminari](https://github.com/amatsuda/kaminari)
11
11
  or [WillPaginate](https://github.com/mislav/will_paginate).
12
12
 
13
- Although the others adapters does not have this feature, it is possible to
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 see in our docs
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(object)
80
+ def pagination_dict(collection)
81
81
  {
82
- current_page: object.current_page,
83
- next_page: object.next_page,
84
- prev_page: object.prev_page,
85
- total_pages: object.total_pages,
86
- total_count: object.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(@post)
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(resource, extra_meta = {})
125
+ def meta_attributes(collection, extra_meta = {})
126
126
  {
127
- current_page: resource.current_page,
128
- next_page: resource.next_page,
129
- prev_page: resource.prev_page,
130
- total_pages: resource.total_pages,
131
- total_count: resource.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.