active_model_serializers 0.10.0 → 0.10.9

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