active_model_serializers 0.10.0 → 0.10.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +239 -2
- data/README.md +171 -34
- data/lib/action_controller/serialization.rb +23 -3
- data/lib/active_model/serializable_resource.rb +2 -0
- data/lib/active_model/serializer/adapter/attributes.rb +2 -0
- data/lib/active_model/serializer/adapter/base.rb +4 -0
- data/lib/active_model/serializer/adapter/json.rb +2 -0
- data/lib/active_model/serializer/adapter/json_api.rb +2 -0
- data/lib/active_model/serializer/adapter/null.rb +2 -0
- data/lib/active_model/serializer/adapter.rb +2 -0
- data/lib/active_model/serializer/array_serializer.rb +10 -5
- data/lib/active_model/serializer/association.rb +64 -10
- data/lib/active_model/serializer/attribute.rb +2 -0
- data/lib/active_model/serializer/belongs_to_reflection.rb +6 -3
- data/lib/active_model/serializer/collection_serializer.rb +48 -13
- data/lib/active_model/serializer/{caching.rb → concerns/caching.rb} +89 -117
- data/lib/active_model/serializer/error_serializer.rb +13 -7
- data/lib/active_model/serializer/errors_serializer.rb +27 -20
- data/lib/active_model/serializer/field.rb +2 -0
- data/lib/active_model/serializer/fieldset.rb +3 -1
- data/lib/active_model/serializer/has_many_reflection.rb +5 -3
- data/lib/active_model/serializer/has_one_reflection.rb +3 -4
- data/lib/active_model/serializer/lazy_association.rb +99 -0
- data/lib/active_model/serializer/link.rb +23 -0
- data/lib/active_model/serializer/lint.rb +136 -130
- data/lib/active_model/serializer/null.rb +2 -0
- data/lib/active_model/serializer/reflection.rb +130 -65
- data/lib/active_model/serializer/version.rb +3 -1
- data/lib/active_model/serializer.rb +321 -86
- data/lib/active_model_serializers/adapter/attributes.rb +17 -57
- data/lib/active_model_serializers/adapter/base.rb +41 -39
- data/lib/active_model_serializers/adapter/json.rb +2 -0
- data/lib/active_model_serializers/adapter/json_api/deserialization.rb +4 -2
- data/lib/active_model_serializers/adapter/json_api/error.rb +2 -0
- data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +2 -0
- data/lib/active_model_serializers/adapter/json_api/link.rb +3 -1
- data/lib/active_model_serializers/adapter/json_api/meta.rb +2 -0
- data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +52 -20
- data/lib/active_model_serializers/adapter/json_api/relationship.rb +77 -23
- data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +41 -10
- data/lib/active_model_serializers/adapter/json_api.rb +84 -65
- data/lib/active_model_serializers/adapter/null.rb +2 -0
- data/lib/active_model_serializers/adapter.rb +9 -1
- data/lib/active_model_serializers/callbacks.rb +2 -0
- data/lib/active_model_serializers/deprecate.rb +3 -2
- data/lib/active_model_serializers/deserialization.rb +4 -0
- data/lib/active_model_serializers/json_pointer.rb +2 -0
- data/lib/active_model_serializers/logging.rb +2 -0
- data/lib/active_model_serializers/lookup_chain.rb +82 -0
- data/lib/active_model_serializers/model/caching.rb +26 -0
- data/lib/active_model_serializers/model.rb +111 -28
- data/lib/active_model_serializers/railtie.rb +7 -1
- data/lib/active_model_serializers/register_jsonapi_renderer.rb +46 -31
- data/lib/active_model_serializers/serializable_resource.rb +10 -7
- data/lib/active_model_serializers/serialization_context.rb +12 -3
- data/lib/active_model_serializers/test/schema.rb +4 -2
- data/lib/active_model_serializers/test/serializer.rb +2 -0
- data/lib/active_model_serializers/test.rb +2 -0
- data/lib/active_model_serializers.rb +35 -10
- data/lib/generators/rails/resource_override.rb +3 -1
- data/lib/generators/rails/serializer_generator.rb +6 -4
- data/lib/grape/active_model_serializers.rb +9 -5
- data/lib/grape/formatters/active_model_serializers.rb +21 -2
- data/lib/grape/helpers/active_model_serializers.rb +3 -0
- data/lib/tasks/rubocop.rake +55 -0
- metadata +104 -296
- data/.github/ISSUE_TEMPLATE.md +0 -29
- data/.github/PULL_REQUEST_TEMPLATE.md +0 -15
- data/.gitignore +0 -35
- data/.rubocop.yml +0 -104
- data/.rubocop_todo.yml +0 -167
- data/.simplecov +0 -110
- data/.travis.yml +0 -43
- data/CONTRIBUTING.md +0 -105
- data/Gemfile +0 -53
- data/Rakefile +0 -103
- data/active_model_serializers.gemspec +0 -66
- data/appveyor.yml +0 -24
- data/bin/bench +0 -171
- data/bin/bench_regression +0 -316
- data/bin/serve_benchmark +0 -39
- data/docs/ARCHITECTURE.md +0 -126
- data/docs/README.md +0 -40
- data/docs/STYLE.md +0 -58
- data/docs/general/adapters.md +0 -245
- data/docs/general/caching.md +0 -52
- data/docs/general/configuration_options.md +0 -100
- data/docs/general/deserialization.md +0 -100
- data/docs/general/getting_started.md +0 -133
- data/docs/general/instrumentation.md +0 -40
- data/docs/general/key_transforms.md +0 -40
- data/docs/general/logging.md +0 -14
- data/docs/general/rendering.md +0 -255
- data/docs/general/serializers.md +0 -372
- data/docs/how-open-source-maintained.jpg +0 -0
- data/docs/howto/add_pagination_links.md +0 -139
- data/docs/howto/add_root_key.md +0 -51
- data/docs/howto/outside_controller_use.md +0 -58
- data/docs/howto/passing_arbitrary_options.md +0 -27
- data/docs/howto/serialize_poro.md +0 -32
- data/docs/howto/test.md +0 -152
- data/docs/integrations/ember-and-json-api.md +0 -112
- data/docs/integrations/grape.md +0 -19
- data/docs/jsonapi/errors.md +0 -56
- data/docs/jsonapi/schema/schema.json +0 -366
- data/docs/jsonapi/schema.md +0 -151
- data/docs/rfcs/0000-namespace.md +0 -106
- data/docs/rfcs/template.md +0 -15
- data/lib/active_model/serializer/associations.rb +0 -100
- data/lib/active_model/serializer/attributes.rb +0 -82
- data/lib/active_model/serializer/collection_reflection.rb +0 -7
- data/lib/active_model/serializer/configuration.rb +0 -35
- data/lib/active_model/serializer/include_tree.rb +0 -111
- data/lib/active_model/serializer/links.rb +0 -35
- data/lib/active_model/serializer/meta.rb +0 -29
- data/lib/active_model/serializer/singular_reflection.rb +0 -7
- data/lib/active_model/serializer/type.rb +0 -25
- data/lib/active_model_serializers/key_transform.rb +0 -70
- data/test/action_controller/adapter_selector_test.rb +0 -53
- data/test/action_controller/explicit_serializer_test.rb +0 -134
- data/test/action_controller/json/include_test.rb +0 -167
- data/test/action_controller/json_api/deserialization_test.rb +0 -112
- data/test/action_controller/json_api/errors_test.rb +0 -41
- data/test/action_controller/json_api/linked_test.rb +0 -197
- data/test/action_controller/json_api/pagination_test.rb +0 -116
- data/test/action_controller/json_api/transform_test.rb +0 -181
- data/test/action_controller/serialization_scope_name_test.rb +0 -229
- data/test/action_controller/serialization_test.rb +0 -469
- data/test/active_model_serializers/adapter_for_test.rb +0 -208
- data/test/active_model_serializers/json_pointer_test.rb +0 -20
- data/test/active_model_serializers/key_transform_test.rb +0 -263
- data/test/active_model_serializers/logging_test.rb +0 -77
- data/test/active_model_serializers/model_test.rb +0 -9
- data/test/active_model_serializers/railtie_test_isolated.rb +0 -63
- data/test/active_model_serializers/serialization_context_test_isolated.rb +0 -58
- data/test/active_model_serializers/test/schema_test.rb +0 -130
- data/test/active_model_serializers/test/serializer_test.rb +0 -62
- data/test/active_record_test.rb +0 -9
- data/test/adapter/deprecation_test.rb +0 -100
- data/test/adapter/json/belongs_to_test.rb +0 -45
- data/test/adapter/json/collection_test.rb +0 -90
- data/test/adapter/json/has_many_test.rb +0 -45
- data/test/adapter/json/transform_test.rb +0 -93
- data/test/adapter/json_api/belongs_to_test.rb +0 -155
- data/test/adapter/json_api/collection_test.rb +0 -95
- data/test/adapter/json_api/errors_test.rb +0 -78
- data/test/adapter/json_api/fields_test.rb +0 -87
- data/test/adapter/json_api/has_many_embed_ids_test.rb +0 -43
- data/test/adapter/json_api/has_many_explicit_serializer_test.rb +0 -96
- data/test/adapter/json_api/has_many_test.rb +0 -144
- data/test/adapter/json_api/has_one_test.rb +0 -80
- data/test/adapter/json_api/json_api_test.rb +0 -35
- data/test/adapter/json_api/linked_test.rb +0 -392
- data/test/adapter/json_api/links_test.rb +0 -93
- data/test/adapter/json_api/pagination_links_test.rb +0 -166
- data/test/adapter/json_api/parse_test.rb +0 -137
- data/test/adapter/json_api/relationship_test.rb +0 -161
- data/test/adapter/json_api/relationships_test.rb +0 -199
- data/test/adapter/json_api/resource_identifier_test.rb +0 -85
- data/test/adapter/json_api/resource_meta_test.rb +0 -100
- data/test/adapter/json_api/toplevel_jsonapi_test.rb +0 -82
- data/test/adapter/json_api/transform_test.rb +0 -502
- data/test/adapter/json_api/type_test.rb +0 -61
- data/test/adapter/json_test.rb +0 -45
- data/test/adapter/null_test.rb +0 -23
- data/test/adapter/polymorphic_test.rb +0 -171
- data/test/adapter_test.rb +0 -67
- data/test/array_serializer_test.rb +0 -22
- data/test/benchmark/app.rb +0 -65
- data/test/benchmark/benchmarking_support.rb +0 -67
- data/test/benchmark/bm_caching.rb +0 -119
- data/test/benchmark/bm_transform.rb +0 -34
- data/test/benchmark/config.ru +0 -3
- data/test/benchmark/controllers.rb +0 -84
- data/test/benchmark/fixtures.rb +0 -219
- data/test/cache_test.rb +0 -485
- data/test/collection_serializer_test.rb +0 -110
- data/test/fixtures/active_record.rb +0 -78
- data/test/fixtures/poro.rb +0 -282
- data/test/generators/scaffold_controller_generator_test.rb +0 -24
- data/test/generators/serializer_generator_test.rb +0 -57
- data/test/grape_test.rb +0 -82
- data/test/include_tree/from_include_args_test.rb +0 -26
- data/test/include_tree/from_string_test.rb +0 -94
- data/test/include_tree/include_args_to_hash_test.rb +0 -64
- data/test/lint_test.rb +0 -49
- data/test/logger_test.rb +0 -18
- data/test/poro_test.rb +0 -9
- data/test/serializable_resource_test.rb +0 -83
- data/test/serializers/association_macros_test.rb +0 -36
- data/test/serializers/associations_test.rb +0 -295
- data/test/serializers/attribute_test.rb +0 -151
- data/test/serializers/attributes_test.rb +0 -52
- data/test/serializers/caching_configuration_test_isolated.rb +0 -170
- data/test/serializers/configuration_test.rb +0 -32
- data/test/serializers/fieldset_test.rb +0 -14
- data/test/serializers/meta_test.rb +0 -196
- data/test/serializers/options_test.rb +0 -21
- data/test/serializers/read_attribute_for_serialization_test.rb +0 -79
- data/test/serializers/root_test.rb +0 -21
- data/test/serializers/serialization_test.rb +0 -55
- data/test/serializers/serializer_for_test.rb +0 -134
- data/test/support/custom_schemas/active_model_serializers/test/schema_test/my/index.json +0 -6
- data/test/support/isolated_unit.rb +0 -79
- data/test/support/rails5_shims.rb +0 -47
- data/test/support/rails_app.rb +0 -45
- data/test/support/schemas/active_model_serializers/test/schema_test/my/index.json +0 -6
- data/test/support/schemas/active_model_serializers/test/schema_test/my/show.json +0 -6
- data/test/support/schemas/custom/show.json +0 -7
- data/test/support/schemas/hyper_schema.json +0 -93
- data/test/support/schemas/render_using_json_api.json +0 -43
- data/test/support/schemas/simple_json_pointers.json +0 -10
- data/test/support/serialization_testing.rb +0 -53
- data/test/test_helper.rb +0 -57
data/docs/general/serializers.md
DELETED
|
@@ -1,372 +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
|
-
[PR please for conditional attributes:)](https://github.com/rails-api/active_model_serializers/pull/1403)
|
|
38
|
-
|
|
39
|
-
### Associations
|
|
40
|
-
|
|
41
|
-
The interface for associations is, generically:
|
|
42
|
-
|
|
43
|
-
> `association_type(association_name, options, &block)`
|
|
44
|
-
|
|
45
|
-
Where:
|
|
46
|
-
|
|
47
|
-
- `association_type` may be `has_one`, `has_many`, `belongs_to`.
|
|
48
|
-
- `association_name` is a method name the serializer calls.
|
|
49
|
-
- optional: `options` may be:
|
|
50
|
-
- `key:` The name used for the serialized association.
|
|
51
|
-
- `serializer:`
|
|
52
|
-
- `if:`
|
|
53
|
-
- `unless:`
|
|
54
|
-
- `virtual_value:`
|
|
55
|
-
- `polymorphic:` defines if polymorphic relation type should be nested in serialized association.
|
|
56
|
-
- optional: `&block` is a context that returns the association's attributes.
|
|
57
|
-
- prevents `association_name` method from being called.
|
|
58
|
-
- return value of block is used as the association value.
|
|
59
|
-
- yields the `serializer` to the block.
|
|
60
|
-
- `include_data false` prevents the `data` key from being rendered in the JSON API relationship.
|
|
61
|
-
|
|
62
|
-
#### ::has_one
|
|
63
|
-
|
|
64
|
-
e.g.
|
|
65
|
-
|
|
66
|
-
```ruby
|
|
67
|
-
has_one :bio
|
|
68
|
-
has_one :blog, key: :site
|
|
69
|
-
has_one :maker, virtual_value: { id: 1 }
|
|
70
|
-
|
|
71
|
-
has_one :blog do |serializer|
|
|
72
|
-
serializer.cached_blog
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def cached_blog
|
|
76
|
-
cache_store.fetch("cached_blog:#{object.updated_at}") do
|
|
77
|
-
Blog.find(object.blog_id)
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
```ruby
|
|
83
|
-
has_one :blog, if: :show_blog?
|
|
84
|
-
# you can also use a string or lambda
|
|
85
|
-
# has_one :blog, if: 'scope.admin?'
|
|
86
|
-
# has_one :blog, if: -> (serializer) { serializer.scope.admin? }
|
|
87
|
-
# has_one :blog, if: -> { scope.admin? }
|
|
88
|
-
|
|
89
|
-
def show_blog?
|
|
90
|
-
scope.admin?
|
|
91
|
-
end
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
#### ::has_many
|
|
95
|
-
|
|
96
|
-
e.g.
|
|
97
|
-
|
|
98
|
-
```ruby
|
|
99
|
-
has_many :comments
|
|
100
|
-
has_many :comments, key: :reviews
|
|
101
|
-
has_many :comments, serializer: CommentPreviewSerializer
|
|
102
|
-
has_many :reviews, virtual_value: [{ id: 1 }, { id: 2 }]
|
|
103
|
-
has_many :comments, key: :last_comments do
|
|
104
|
-
last(1)
|
|
105
|
-
end
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
#### ::belongs_to
|
|
109
|
-
|
|
110
|
-
e.g.
|
|
111
|
-
|
|
112
|
-
```ruby
|
|
113
|
-
belongs_to :author, serializer: AuthorPreviewSerializer
|
|
114
|
-
belongs_to :author, key: :writer
|
|
115
|
-
belongs_to :post
|
|
116
|
-
belongs_to :blog
|
|
117
|
-
def blog
|
|
118
|
-
Blog.new(id: 999, name: 'Custom blog')
|
|
119
|
-
end
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
### Polymorphic Relationships
|
|
123
|
-
|
|
124
|
-
Polymorphic relationships are serialized by specifying the relationship, like any other association. For example:
|
|
125
|
-
|
|
126
|
-
```ruby
|
|
127
|
-
class PictureSerializer < ActiveModel::Serializer
|
|
128
|
-
has_one :imageable
|
|
129
|
-
end
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
For more context, see the [tests](../../test/adapter/polymorphic_test.rb) for each adapter.
|
|
133
|
-
|
|
134
|
-
### Caching
|
|
135
|
-
|
|
136
|
-
#### ::cache
|
|
137
|
-
|
|
138
|
-
e.g.
|
|
139
|
-
|
|
140
|
-
```ruby
|
|
141
|
-
cache key: 'post', expires_in: 0.1, skip_digest: true
|
|
142
|
-
cache expires_in: 1.day, skip_digest: true
|
|
143
|
-
cache key: 'writer', skip_digest: true
|
|
144
|
-
cache only: [:name], skip_digest: true
|
|
145
|
-
cache except: [:content], skip_digest: true
|
|
146
|
-
cache key: 'blog'
|
|
147
|
-
cache only: [:id]
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
#### #cache_key
|
|
151
|
-
|
|
152
|
-
e.g.
|
|
153
|
-
|
|
154
|
-
```ruby
|
|
155
|
-
# Uses a custom non-time-based cache key
|
|
156
|
-
def cache_key
|
|
157
|
-
"#{self.class.name.downcase}/#{self.id}"
|
|
158
|
-
end
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
### Other
|
|
162
|
-
|
|
163
|
-
#### ::type
|
|
164
|
-
|
|
165
|
-
The `::type` method defines the JSONAPI [type](http://jsonapi.org/format/#document-resource-object-identification) that will be rendered for this serializer.
|
|
166
|
-
It either takes a `String` or `Symbol` as parameter.
|
|
167
|
-
|
|
168
|
-
Note: This method is useful only when using the `:json_api` adapter.
|
|
169
|
-
|
|
170
|
-
Examples:
|
|
171
|
-
```ruby
|
|
172
|
-
class UserProfileSerializer < ActiveModel::Serializer
|
|
173
|
-
type 'profile'
|
|
174
|
-
end
|
|
175
|
-
class AuthorProfileSerializer < ActiveModel::Serializer
|
|
176
|
-
type :profile
|
|
177
|
-
end
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
With the `:json_api` adapter, the previous serializers would be rendered as:
|
|
181
|
-
|
|
182
|
-
``` json
|
|
183
|
-
{
|
|
184
|
-
"data": {
|
|
185
|
-
"id": "1",
|
|
186
|
-
"type": "profile"
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
#### ::link
|
|
192
|
-
|
|
193
|
-
```ruby
|
|
194
|
-
link :self do
|
|
195
|
-
href "https://example.com/link_author/#{object.id}"
|
|
196
|
-
end
|
|
197
|
-
link :author { link_author_url(object) }
|
|
198
|
-
link :link_authors { link_authors_url }
|
|
199
|
-
link :other, 'https://example.com/resource'
|
|
200
|
-
link :posts { link_author_posts_url(object) }
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
#### #object
|
|
204
|
-
|
|
205
|
-
The object being serialized.
|
|
206
|
-
|
|
207
|
-
#### #root
|
|
208
|
-
|
|
209
|
-
PR please :)
|
|
210
|
-
|
|
211
|
-
#### #scope
|
|
212
|
-
|
|
213
|
-
Allows you to include in the serializer access to an external method.
|
|
214
|
-
|
|
215
|
-
It's intended to provide an authorization context to the serializer, so that
|
|
216
|
-
you may e.g. show an admin all comments on a post, else only published comments.
|
|
217
|
-
|
|
218
|
-
- `scope` is a method on the serializer instance that comes from `options[:scope]`. It may be nil.
|
|
219
|
-
- `scope_name` is an option passed to the new serializer (`options[:scope_name]`). The serializer
|
|
220
|
-
defines a method with that name that calls the `scope`, e.g. `def current_user; scope; end`.
|
|
221
|
-
Note: it does not define the method if the serializer instance responds to it.
|
|
222
|
-
|
|
223
|
-
That's a lot of words, so here's some examples:
|
|
224
|
-
|
|
225
|
-
First, let's assume the serializer is instantiated in the controller, since that's the usual scenario.
|
|
226
|
-
We'll refer to the serialization context as `controller`.
|
|
227
|
-
|
|
228
|
-
| options | `Serializer#scope` | method definition |
|
|
229
|
-
|-------- | ------------------|--------------------|
|
|
230
|
-
| `scope: current_user, scope_name: :current_user` | `current_user` | `Serializer#current_user` calls `controller.current_user`
|
|
231
|
-
| `scope: view_context, scope_name: :view_context` | `view_context` | `Serializer#view_context` calls `controller.view_context`
|
|
232
|
-
|
|
233
|
-
We can take advantage of the scope to customize the objects returned based
|
|
234
|
-
on the current user (scope).
|
|
235
|
-
|
|
236
|
-
For example, we can limit the posts the current user sees to those they created:
|
|
237
|
-
|
|
238
|
-
```ruby
|
|
239
|
-
class PostSerializer < ActiveModel::Serializer
|
|
240
|
-
attributes :id, :title, :body
|
|
241
|
-
|
|
242
|
-
# scope comments to those created_by the current user
|
|
243
|
-
has_many :comments do
|
|
244
|
-
object.comments.where(created_by: current_user)
|
|
245
|
-
end
|
|
246
|
-
end
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
Whether you write the method as above or as `object.comments.where(created_by: scope)`
|
|
250
|
-
is a matter of preference (assuming `scope_name` has been set).
|
|
251
|
-
|
|
252
|
-
##### Controller Authorization Context
|
|
253
|
-
|
|
254
|
-
In the controller, the scope/scope_name options are equal to
|
|
255
|
-
the [`serialization_scope`method](https://github.com/rails-api/active_model_serializers/blob/d02cd30fe55a3ea85e1d351b6e039620903c1871/lib/action_controller/serialization.rb#L13-L20),
|
|
256
|
-
which is `:current_user`, by default.
|
|
257
|
-
|
|
258
|
-
Specfically, the `scope_name` is defaulted to `:current_user`, and may be set as
|
|
259
|
-
`serialization_scope :view_context`. The `scope` is set to `send(scope_name)` when `scope_name` is
|
|
260
|
-
present and the controller responds to `scope_name`.
|
|
261
|
-
|
|
262
|
-
Thus, in a serializer, the controller provides `current_user` as the
|
|
263
|
-
current authorization scope when you call `render :json`.
|
|
264
|
-
|
|
265
|
-
**IMPORTANT**: Since the scope is set at render, you may want to customize it so that `current_user` isn't
|
|
266
|
-
called on every request. This was [also a problem](https://github.com/rails-api/active_model_serializers/pull/1252#issuecomment-159810477)
|
|
267
|
-
in [`0.9`](https://github.com/rails-api/active_model_serializers/tree/0-9-stable#customizing-scope).
|
|
268
|
-
|
|
269
|
-
We can change the scope from `current_user` to `view_context`.
|
|
270
|
-
|
|
271
|
-
```diff
|
|
272
|
-
class SomeController < ActionController::Base
|
|
273
|
-
+ serialization_scope :view_context
|
|
274
|
-
|
|
275
|
-
def current_user
|
|
276
|
-
User.new(id: 2, name: 'Bob', admin: true)
|
|
277
|
-
end
|
|
278
|
-
|
|
279
|
-
def edit
|
|
280
|
-
user = User.new(id: 1, name: 'Pete')
|
|
281
|
-
render json: user, serializer: AdminUserSerializer, adapter: :json_api
|
|
282
|
-
end
|
|
283
|
-
end
|
|
284
|
-
```
|
|
285
|
-
|
|
286
|
-
We could then use the controller method `view_context` in our serializer, like so:
|
|
287
|
-
|
|
288
|
-
```diff
|
|
289
|
-
class AdminUserSerializer < ActiveModel::Serializer
|
|
290
|
-
attributes :id, :name, :can_edit
|
|
291
|
-
|
|
292
|
-
def can_edit?
|
|
293
|
-
+ view_context.current_user.admin?
|
|
294
|
-
end
|
|
295
|
-
end
|
|
296
|
-
```
|
|
297
|
-
|
|
298
|
-
So that when we render the `#edit` action, we'll get
|
|
299
|
-
|
|
300
|
-
```json
|
|
301
|
-
{"data":{"id":"1","type":"users","attributes":{"name":"Pete","can_edit":true}}}
|
|
302
|
-
```
|
|
303
|
-
|
|
304
|
-
Where `can_edit` is `view_context.current_user.admin?` (true).
|
|
305
|
-
|
|
306
|
-
#### #read_attribute_for_serialization(key)
|
|
307
|
-
|
|
308
|
-
The serialized value for a given key. e.g. `read_attribute_for_serialization(:title) #=> 'Hello World'`
|
|
309
|
-
|
|
310
|
-
#### #links
|
|
311
|
-
|
|
312
|
-
PR please :)
|
|
313
|
-
|
|
314
|
-
#### #json_key
|
|
315
|
-
|
|
316
|
-
PR please :)
|
|
317
|
-
|
|
318
|
-
## Examples
|
|
319
|
-
|
|
320
|
-
Given two models, a `Post(title: string, body: text)` and a
|
|
321
|
-
`Comment(name: string, body: text, post_id: integer)`, you will have two
|
|
322
|
-
serializers:
|
|
323
|
-
|
|
324
|
-
```ruby
|
|
325
|
-
class PostSerializer < ActiveModel::Serializer
|
|
326
|
-
cache key: 'posts', expires_in: 3.hours
|
|
327
|
-
attributes :title, :body
|
|
328
|
-
|
|
329
|
-
has_many :comments
|
|
330
|
-
end
|
|
331
|
-
```
|
|
332
|
-
|
|
333
|
-
and
|
|
334
|
-
|
|
335
|
-
```ruby
|
|
336
|
-
class CommentSerializer < ActiveModel::Serializer
|
|
337
|
-
attributes :name, :body
|
|
338
|
-
|
|
339
|
-
belongs_to :post
|
|
340
|
-
end
|
|
341
|
-
```
|
|
342
|
-
|
|
343
|
-
Generally speaking, you, as a user of ActiveModelSerializers, will write (or generate) these
|
|
344
|
-
serializer classes.
|
|
345
|
-
|
|
346
|
-
## More Info
|
|
347
|
-
|
|
348
|
-
For more information, see [the Serializer class on GitHub](https://github.com/rails-api/active_model_serializers/blob/master/lib/active_model/serializer.rb)
|
|
349
|
-
|
|
350
|
-
## Overriding association methods
|
|
351
|
-
|
|
352
|
-
To override an association, call `has_many`, `has_one` or `belongs_to` with a block:
|
|
353
|
-
|
|
354
|
-
```ruby
|
|
355
|
-
class PostSerializer < ActiveModel::Serializer
|
|
356
|
-
has_many :comments do
|
|
357
|
-
object.comments.active
|
|
358
|
-
end
|
|
359
|
-
end
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
## Overriding attribute methods
|
|
363
|
-
|
|
364
|
-
To override an attribute, call `attribute` with a block:
|
|
365
|
-
|
|
366
|
-
```ruby
|
|
367
|
-
class PostSerializer < ActiveModel::Serializer
|
|
368
|
-
attribute :body do
|
|
369
|
-
object.body.downcase
|
|
370
|
-
end
|
|
371
|
-
end
|
|
372
|
-
```
|
|
Binary file
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
[Back to Guides](../README.md)
|
|
2
|
-
|
|
3
|
-
# How to add pagination links
|
|
4
|
-
|
|
5
|
-
### JSON API adapter
|
|
6
|
-
|
|
7
|
-
Pagination links will be included in your response automatically as long as
|
|
8
|
-
the resource is paginated and if you are using the ```JsonApi``` adapter.
|
|
9
|
-
|
|
10
|
-
If you want pagination links in your response, use [Kaminari](https://github.com/amatsuda/kaminari)
|
|
11
|
-
or [WillPaginate](https://github.com/mislav/will_paginate).
|
|
12
|
-
|
|
13
|
-
Although the others adapters does not have this feature, it is possible to
|
|
14
|
-
implement pagination links to `JSON` adapter. For more information about it,
|
|
15
|
-
please see in our docs
|
|
16
|
-
|
|
17
|
-
###### Kaminari examples
|
|
18
|
-
|
|
19
|
-
```ruby
|
|
20
|
-
#array
|
|
21
|
-
@posts = Kaminari.paginate_array([1, 2, 3]).page(3).per(1)
|
|
22
|
-
render json: @posts
|
|
23
|
-
|
|
24
|
-
#active_record
|
|
25
|
-
@posts = Post.page(3).per(1)
|
|
26
|
-
render json: @posts
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
###### WillPaginate examples
|
|
30
|
-
|
|
31
|
-
```ruby
|
|
32
|
-
#array
|
|
33
|
-
@posts = [1,2,3].paginate(page: 3, per_page: 1)
|
|
34
|
-
render json: @posts
|
|
35
|
-
|
|
36
|
-
#active_record
|
|
37
|
-
@posts = Post.page(3).per_page(1)
|
|
38
|
-
render json: @posts
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
```ruby
|
|
42
|
-
ActiveModelSerializers.config.adapter = :json_api
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
ex:
|
|
46
|
-
```json
|
|
47
|
-
{
|
|
48
|
-
"data": [
|
|
49
|
-
{
|
|
50
|
-
"type": "articles",
|
|
51
|
-
"id": "3",
|
|
52
|
-
"attributes": {
|
|
53
|
-
"title": "JSON API paints my bikeshed!",
|
|
54
|
-
"body": "The shortest article. Ever.",
|
|
55
|
-
"created": "2015-05-22T14:56:29.000Z",
|
|
56
|
-
"updated": "2015-05-22T14:56:28.000Z"
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
],
|
|
60
|
-
"links": {
|
|
61
|
-
"self": "http://example.com/articles?page[number]=3&page[size]=1",
|
|
62
|
-
"first": "http://example.com/articles?page[number]=1&page[size]=1",
|
|
63
|
-
"prev": "http://example.com/articles?page[number]=2&page[size]=1",
|
|
64
|
-
"next": "http://example.com/articles?page[number]=4&page[size]=1",
|
|
65
|
-
"last": "http://example.com/articles?page[number]=13&page[size]=1"
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
ActiveModelSerializers pagination relies on a paginated collection with the methods `current_page`, `total_pages`, and `size`, such as are supported by both [Kaminari](https://github.com/amatsuda/kaminari) or [WillPaginate](https://github.com/mislav/will_paginate).
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
### JSON adapter
|
|
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.
|
|
76
|
-
|
|
77
|
-
Add this method to your base API controller.
|
|
78
|
-
|
|
79
|
-
```ruby
|
|
80
|
-
def pagination_dict(object)
|
|
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
|
|
87
|
-
}
|
|
88
|
-
end
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
Then, use it on your render method.
|
|
92
|
-
|
|
93
|
-
```ruby
|
|
94
|
-
render json: posts, meta: pagination_dict(posts)
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
ex.
|
|
98
|
-
```json
|
|
99
|
-
{
|
|
100
|
-
"posts": [
|
|
101
|
-
{
|
|
102
|
-
"id": 2,
|
|
103
|
-
"title": "JSON API paints my bikeshed!",
|
|
104
|
-
"body": "The shortest article. Ever."
|
|
105
|
-
}
|
|
106
|
-
],
|
|
107
|
-
"meta": {
|
|
108
|
-
"current_page": 3,
|
|
109
|
-
"next_page": 4,
|
|
110
|
-
"prev_page": 2,
|
|
111
|
-
"total_pages": 10,
|
|
112
|
-
"total_count": 10
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
```
|
|
116
|
-
|
|
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
|
-
|
|
119
|
-
```ruby
|
|
120
|
-
render json: @posts, each_serializer: PostPreviewSerializer, meta: meta_attributes(@post)
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
```ruby
|
|
124
|
-
#expects pagination!
|
|
125
|
-
def meta_attributes(resource, extra_meta = {})
|
|
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
|
|
132
|
-
}.merge(extra_meta)
|
|
133
|
-
end
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
### Attributes adapter
|
|
138
|
-
|
|
139
|
-
This adapter does not allow us to use `meta` key, due to that it is not possible to add pagination links.
|
data/docs/howto/add_root_key.md
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
# How to add root key
|
|
2
|
-
|
|
3
|
-
Add the root key to your API is quite simple with ActiveModelSerializers. The **Adapter** is what determines the format of your JSON response. The default adapter is the ```Attributes``` which doesn't have the root key, so your response is something similar to:
|
|
4
|
-
|
|
5
|
-
```json
|
|
6
|
-
{
|
|
7
|
-
"id": 1,
|
|
8
|
-
"title": "Awesome Post Tile",
|
|
9
|
-
"content": "Post content"
|
|
10
|
-
}
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
In order to add the root key you need to use the ```JSON``` Adapter, you can change this in an initializer:
|
|
14
|
-
|
|
15
|
-
```ruby
|
|
16
|
-
ActiveModelSerializers.config.adapter = :json
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
You can also specify a class as adapter, as long as it complies with the ActiveModelSerializers adapters interface.
|
|
20
|
-
It will add the root key to all your serialized endpoints.
|
|
21
|
-
|
|
22
|
-
ex:
|
|
23
|
-
|
|
24
|
-
```json
|
|
25
|
-
{
|
|
26
|
-
"post": {
|
|
27
|
-
"id": 1,
|
|
28
|
-
"title": "Awesome Post Tile",
|
|
29
|
-
"content": "Post content"
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
or if it returns a collection:
|
|
35
|
-
|
|
36
|
-
```json
|
|
37
|
-
{
|
|
38
|
-
"posts": [
|
|
39
|
-
{
|
|
40
|
-
"id": 1,
|
|
41
|
-
"title": "Awesome Post Tile",
|
|
42
|
-
"content": "Post content"
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
"id": 2,
|
|
46
|
-
"title": "Another Post Tile",
|
|
47
|
-
"content": "Another post content"
|
|
48
|
-
}
|
|
49
|
-
]
|
|
50
|
-
}
|
|
51
|
-
```
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
[Back to Guides](../README.md)
|
|
2
|
-
|
|
3
|
-
## Using ActiveModelSerializers Outside Of A Controller
|
|
4
|
-
|
|
5
|
-
### Serializing a resource
|
|
6
|
-
|
|
7
|
-
In ActiveModelSerializers versions 0.10 or later, serializing resources outside of the controller context is fairly simple:
|
|
8
|
-
|
|
9
|
-
```ruby
|
|
10
|
-
# Create our resource
|
|
11
|
-
post = Post.create(title: "Sample post", body: "I love Active Model Serializers!")
|
|
12
|
-
|
|
13
|
-
# Optional options parameters
|
|
14
|
-
options = {}
|
|
15
|
-
|
|
16
|
-
# Create a serializable resource instance
|
|
17
|
-
serializable_resource = ActiveModelSerializers::SerializableResource.new(post, options)
|
|
18
|
-
|
|
19
|
-
# Convert your resource into json
|
|
20
|
-
model_json = serializable_resource.as_json
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
### Looking up the Serializer for a Resource
|
|
24
|
-
|
|
25
|
-
If you want to retrieve a serializer for a specific resource, you can do the following:
|
|
26
|
-
|
|
27
|
-
```ruby
|
|
28
|
-
# Create our resource
|
|
29
|
-
post = Post.create(title: "Another Example", body: "So much fun.")
|
|
30
|
-
|
|
31
|
-
# Optional options parameters
|
|
32
|
-
options = {}
|
|
33
|
-
|
|
34
|
-
# Retrieve the default serializer for posts
|
|
35
|
-
serializer = ActiveModel::Serializer.serializer_for(post, options)
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
You could also retrieve the serializer via:
|
|
39
|
-
|
|
40
|
-
```ruby
|
|
41
|
-
ActiveModelSerializers::SerializableResource.new(post, options).serializer
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
Both approaches will return an instance, if any, of the resource's serializer.
|
|
45
|
-
|
|
46
|
-
## Serializing before controller render
|
|
47
|
-
|
|
48
|
-
At times, you might want to use a serializer without rendering it to the view. For those cases, you can create an instance of `ActiveModelSerializers::SerializableResource` with
|
|
49
|
-
the resource you want to be serialized and call `.as_json`.
|
|
50
|
-
|
|
51
|
-
```ruby
|
|
52
|
-
def create
|
|
53
|
-
message = current_user.messages.create!(message_params)
|
|
54
|
-
message_json = ActiveModelSerializers::SerializableResource.new(message).as_json
|
|
55
|
-
MessageCreationWorker.perform(message_json)
|
|
56
|
-
head 204
|
|
57
|
-
end
|
|
58
|
-
```
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
[Back to Guides](../README.md)
|
|
2
|
-
|
|
3
|
-
# Passing Arbitrary Options To A Serializer
|
|
4
|
-
|
|
5
|
-
In addition to the [`serialization_scope`](../general/serializers.md#scope), any options passed to `render`
|
|
6
|
-
that are not reserved for the [adapter](../general/rendering.md#adapter_opts)
|
|
7
|
-
are available in the serializer as [instance_options](../general/serializers.md#instance_options).
|
|
8
|
-
|
|
9
|
-
For example, we could pass in a field, such as `user_id` into our serializer.
|
|
10
|
-
|
|
11
|
-
```ruby
|
|
12
|
-
# posts_controller.rb
|
|
13
|
-
class PostsController < ApplicationController
|
|
14
|
-
def dashboard
|
|
15
|
-
render json: @post, user_id: 12
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
# post_serializer.rb
|
|
20
|
-
class PostSerializer < ActiveModel::Serializer
|
|
21
|
-
attributes :id, :title, :body
|
|
22
|
-
|
|
23
|
-
def comments_by_me
|
|
24
|
-
Comments.where(user_id: instance_options[:user_id], post_id: object.id)
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
```
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
[Back to Guides](../README.md)
|
|
2
|
-
|
|
3
|
-
# How to serialize a Plain-Old Ruby Object (PORO)
|
|
4
|
-
|
|
5
|
-
When you are first getting started with ActiveModelSerializers, it may seem only `ActiveRecord::Base` objects can be serializable, but pretty much any object can be serializable with ActiveModelSerializers. Here is an example of a PORO that is serializable:
|
|
6
|
-
```ruby
|
|
7
|
-
# my_model.rb
|
|
8
|
-
class MyModel
|
|
9
|
-
alias :read_attribute_for_serialization :send
|
|
10
|
-
attr_accessor :id, :name, :level
|
|
11
|
-
|
|
12
|
-
def initialize(attributes)
|
|
13
|
-
@id = attributes[:id]
|
|
14
|
-
@name = attributes[:name]
|
|
15
|
-
@level = attributes[:level]
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def self.model_name
|
|
19
|
-
@_model_name ||= ActiveModel::Name.new(self)
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
Fortunately, ActiveModelSerializers provides a [`ActiveModelSerializers::Model`](https://github.com/rails-api/active_model_serializers/blob/master/lib/active_model_serializers/model.rb) which you can use in production code that will make your PORO a lot cleaner. The above code now becomes:
|
|
25
|
-
```ruby
|
|
26
|
-
# my_model.rb
|
|
27
|
-
class MyModel < ActiveModelSerializers::Model
|
|
28
|
-
attr_accessor :id, :name, :level
|
|
29
|
-
end
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
The default serializer would be `MyModelSerializer`.
|