active_model_serializers 0.8.4 → 0.9.0.alpha1
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 +4 -4
- data/CHANGELOG.md +30 -45
- data/CONTRIBUTING.md +20 -0
- data/DESIGN.textile +4 -4
- data/{MIT-LICENSE.txt → MIT-LICENSE} +0 -0
- data/README.md +187 -113
- data/lib/action_controller/serialization.rb +30 -16
- data/lib/active_model/array_serializer.rb +36 -82
- data/lib/active_model/default_serializer.rb +22 -0
- data/lib/active_model/serializable.rb +25 -0
- data/lib/active_model/serializer.rb +126 -447
- data/lib/active_model/serializer/associations.rb +53 -211
- data/lib/active_model/serializer/config.rb +31 -0
- data/lib/active_model/serializer/generators/resource_override.rb +13 -0
- data/lib/{generators → active_model/serializer/generators}/serializer/USAGE +0 -0
- data/lib/active_model/serializer/generators/serializer/scaffold_controller_generator.rb +14 -0
- data/lib/active_model/serializer/generators/serializer/serializer_generator.rb +37 -0
- data/lib/active_model/serializer/generators/serializer/templates/controller.rb +93 -0
- data/lib/active_model/serializer/generators/serializer/templates/serializer.rb +8 -0
- data/lib/active_model/serializer/railtie.rb +10 -0
- data/lib/active_model/{serializers → serializer}/version.rb +1 -1
- data/lib/active_model/serializer_support.rb +5 -0
- data/lib/active_model_serializers.rb +7 -86
- data/test/coverage_setup.rb +15 -0
- data/test/fixtures/active_record.rb +92 -0
- data/test/fixtures/poro.rb +64 -0
- data/test/integration/action_controller/serialization_test.rb +234 -0
- data/test/integration/active_record/active_record_test.rb +77 -0
- data/test/integration/generators/resource_generator_test.rb +26 -0
- data/test/integration/generators/scaffold_controller_generator_test.rb +67 -0
- data/test/integration/generators/serializer_generator_test.rb +41 -0
- data/test/test_app.rb +11 -0
- data/test/test_helper.rb +7 -41
- data/test/tmp/app/serializers/account_serializer.rb +3 -0
- data/test/unit/active_model/array_serializer/meta_test.rb +53 -0
- data/test/unit/active_model/array_serializer/root_test.rb +102 -0
- data/test/unit/active_model/array_serializer/scope_test.rb +24 -0
- data/test/unit/active_model/array_serializer/serialization_test.rb +83 -0
- data/test/unit/active_model/default_serializer_test.rb +13 -0
- data/test/unit/active_model/serializer/associations/build_serializer_test.rb +21 -0
- data/test/unit/active_model/serializer/associations_test.rb +19 -0
- data/test/unit/active_model/serializer/attributes_test.rb +41 -0
- data/test/unit/active_model/serializer/config_test.rb +86 -0
- data/test/unit/active_model/serializer/filter_test.rb +49 -0
- data/test/unit/active_model/serializer/has_many_test.rb +173 -0
- data/test/unit/active_model/serializer/has_one_test.rb +151 -0
- data/test/unit/active_model/serializer/meta_test.rb +39 -0
- data/test/unit/active_model/serializer/root_test.rb +117 -0
- data/test/unit/active_model/serializer/scope_test.rb +49 -0
- metadata +78 -74
- data/.gitignore +0 -18
- data/.travis.yml +0 -34
- data/Gemfile +0 -38
- data/Rakefile +0 -22
- data/active_model_serializers.gemspec +0 -24
- data/appveyor.yml +0 -27
- data/bench/perf.rb +0 -43
- data/cruft.md +0 -19
- data/lib/active_record/serializer_override.rb +0 -16
- data/lib/generators/resource_override.rb +0 -13
- data/lib/generators/serializer/serializer_generator.rb +0 -42
- data/lib/generators/serializer/templates/serializer.rb +0 -19
- data/test/array_serializer_test.rb +0 -75
- data/test/association_test.rb +0 -592
- data/test/caching_test.rb +0 -177
- data/test/generators_test.rb +0 -85
- data/test/no_serialization_scope_test.rb +0 -34
- data/test/serialization_scope_name_test.rb +0 -67
- data/test/serialization_test.rb +0 -396
- data/test/serializer_support_test.rb +0 -51
- data/test/serializer_test.rb +0 -1466
- data/test/test_fakes.rb +0 -218
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aeb402f8407aece224529052410e2ad33485d7eb
|
4
|
+
data.tar.gz: db4621bc2e62921b75a8e02e77b30e4782951b1a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5496e9420a975333a78f239eb2bbeb680f4240ec22e1bdbbe989fceb480325e14fbd96ab706510f0b0297b8317d85298451b034eabb5f1e67627e03bd0aa5c57
|
7
|
+
data.tar.gz: 2320ddcf2bf5c13028669dabc470331008de7e3fe79bf3f4ffb4d70df701731061541ccfc4ed57160dc520b8637e02e75b8510bfb6c72470be4ffd2603618be1
|
data/CHANGELOG.md
CHANGED
@@ -1,46 +1,42 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
-
|
10
|
-
-
|
11
|
-
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
- [#607](https://github.com/rails-api/active_model_serializers/pull/607) ruby syntax highlights (@zigomir)
|
25
|
-
- [#602](https://github.com/rails-api/active_model_serializers/pull/602) Add DSL for associations (@JordanFaust)
|
26
|
-
|
27
|
-
### 0.8.1 (May 6, 2013)
|
1
|
+
# VERSION 0.9.0.pre
|
2
|
+
|
3
|
+
* The following methods were removed
|
4
|
+
- Model#active\_model\_serializer
|
5
|
+
- Serializer#include!
|
6
|
+
- Serializer#include?
|
7
|
+
- Serializer#attr\_disabled=
|
8
|
+
- Serializer#cache
|
9
|
+
- Serializer#perform\_caching
|
10
|
+
- Serializer#schema (needs more discussion)
|
11
|
+
- Serializer#attribute
|
12
|
+
- Serializer#include\_#{name}? (filter method added)
|
13
|
+
- Serializer#attributes (took a hash)
|
14
|
+
|
15
|
+
* The following things were added
|
16
|
+
- Serializer#filter method
|
17
|
+
- CONFIG object
|
18
|
+
|
19
|
+
* Remove support for ruby 1.8 versions.
|
20
|
+
|
21
|
+
* Require rails >= 3.2.
|
22
|
+
|
23
|
+
# VERSION 0.8.1
|
28
24
|
|
29
25
|
* Fix bug whereby a serializer using 'options' would blow up.
|
30
26
|
|
31
|
-
|
27
|
+
# VERSION 0.8.0
|
32
28
|
|
33
29
|
* Attributes can now have optional types.
|
34
30
|
|
35
31
|
* A new DefaultSerializer ensures that POROs behave the same way as ActiveModels.
|
36
32
|
|
37
|
-
* If you wish to override ActiveRecord::Base#
|
38
|
-
'
|
33
|
+
* If you wish to override ActiveRecord::Base#to\_Json, you can now require
|
34
|
+
'active\_record/serializer\_override'. We don't recommend you do this, but
|
39
35
|
many users do, so we've left it optional.
|
40
36
|
|
41
37
|
* Fixed a bug where ActionController wouldn't always have MimeResponds.
|
42
38
|
|
43
|
-
* An
|
39
|
+
* An optional caching feature allows you to cache JSON & hashes that AMS uses.
|
44
40
|
Adding 'cached true' to your Serializers will turn on this cache.
|
45
41
|
|
46
42
|
* URL helpers used inside of Engines now work properly.
|
@@ -64,7 +60,7 @@
|
|
64
60
|
* Pass through serialization options (such as `:include`) when a model
|
65
61
|
has no serializer defined.
|
66
62
|
|
67
|
-
|
63
|
+
# VERSION 0.7.0
|
68
64
|
|
69
65
|
* ```embed_key``` option to allow embedding by attributes other than IDs
|
70
66
|
* Fix rendering nil with custom serializer
|
@@ -74,7 +70,7 @@
|
|
74
70
|
* Serializer Reloading via ActiveSupport::DescendantsTracker
|
75
71
|
* Reduce double map to once; Fixes datamapper eager loading.
|
76
72
|
|
77
|
-
|
73
|
+
# VERSION 0.6.0
|
78
74
|
|
79
75
|
* Serialize sets properly
|
80
76
|
* Add root option to ArraySerializer
|
@@ -85,18 +81,7 @@
|
|
85
81
|
* Allow serialization_scope to be disabled with serialization_scope nil
|
86
82
|
* Array serializer should support pure ruby objects besides serializers
|
87
83
|
|
88
|
-
|
89
|
-
|
90
|
-
### [0.5.2 (June 5, 2012)](https://github.com/rails-api/active_model_serializers/commit/615afd125c260432d456dc8be845867cf87ea118#diff-0c5c12f311d3b54734fff06069efd2ac)
|
91
|
-
|
92
|
-
### [0.5.1 (May 23, 2012)](https://github.com/rails-api/active_model_serializers/commit/00194ec0e41831802fcbf893a34c0bb0853ebe14#diff-0c5c12f311d3b54734fff06069efd2ac)
|
93
|
-
|
94
|
-
### [0.5.0 (May 16, 2012)](https://github.com/rails-api/active_model_serializers/commit/33d4842dcd35c7167b0b33fc0abcf00fb2c92286)
|
84
|
+
# VERSION 0.5.0
|
95
85
|
|
96
86
|
* First tagged version
|
97
87
|
* Changes generators to always generate an ApplicationSerializer
|
98
|
-
|
99
|
-
## [0.1.0 (December 21, 2011)](https://github.com/rails-api/active_model_serializers/commit/1e0c9ef93b96c640381575dcd30be07ac946818b)
|
100
|
-
|
101
|
-
## First Commit as [Rails Serializers 0.0.1](https://github.com/rails-api/active_model_serializers/commit/d72b66d4c5355b0ff0a75a04895fcc4ea5b0c65e)
|
102
|
-
(December 1, 2011).
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Contributing to AMS
|
2
|
+
===================
|
3
|
+
|
4
|
+
First of all, **thank you**!
|
5
|
+
|
6
|
+
Now, for the details:
|
7
|
+
|
8
|
+
Please file issues on the [GitHub Issues
|
9
|
+
list](https://github.com/rails-api/active_model_serializers/issues).
|
10
|
+
|
11
|
+
Please discuss new features or ask for feedback about a new feature [on
|
12
|
+
rails-api-core](https://groups.google.com/forum/#!forum/rails-api-core).
|
13
|
+
|
14
|
+
If you want a feature implemented, the best way to get it done is to submit a
|
15
|
+
pull request that implements it. Tests and docs would be nice.
|
16
|
+
|
17
|
+
Please include a CHANGELOG with all entries that change behavior.
|
18
|
+
|
19
|
+
:heart: :sparkling_heart: :heart:
|
20
|
+
|
data/DESIGN.textile
CHANGED
@@ -358,8 +358,8 @@ Here is an example:
|
|
358
358
|
|
359
359
|
<pre lang="ruby">
|
360
360
|
class UserSerializer < ActiveModel::Serializer
|
361
|
-
has_many :followed_posts, :
|
362
|
-
has_one :owned_account, :
|
361
|
+
has_many :followed_posts, key: :posts
|
362
|
+
has_one :owned_account, key: :account
|
363
363
|
end
|
364
364
|
</pre>
|
365
365
|
|
@@ -370,8 +370,8 @@ to set it explicitly:
|
|
370
370
|
|
371
371
|
<pre lang="ruby">
|
372
372
|
class UserSerializer < ActiveModel::Serializer
|
373
|
-
has_many :followed_posts, :
|
374
|
-
has_one :owne_account, :
|
373
|
+
has_many :followed_posts, key: :posts, serializer: CustomPostSerializer
|
374
|
+
has_one :owne_account, key: :account, serializer: PrivateAccountSerializer
|
375
375
|
end
|
376
376
|
</pre>
|
377
377
|
|
File without changes
|
data/README.md
CHANGED
@@ -1,10 +1,20 @@
|
|
1
|
-
[](https://travis-ci.org/rails-api/active_model_serializers)
|
1
|
+
[](https://travis-ci.org/rails-api/active_model_serializers)
|
2
|
+
[](https://codeclimate.com/github/rails-api/active_model_serializers)
|
3
|
+
[](https://coveralls.io/r/rails-api/active_model_serializers)
|
2
4
|
|
3
|
-
#
|
5
|
+
# ActiveModel::Serializers
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
7
|
+
## Master - 0.9.0
|
8
|
+
|
9
|
+
**master is under development, there are some incompatible changes with the current stable release.**
|
10
|
+
|
11
|
+
If you want to read the stable documentation visit [0.8 README](https://github.com/rails-api/active_model_serializers/blob/0-8-stable/README.md)
|
12
|
+
|
13
|
+
## Purpose
|
14
|
+
|
15
|
+
`ActiveModel::Serializers` encapsulates the JSON serialization of objects.
|
16
|
+
Objects that respond to read\_attribute\_for\_serialization
|
17
|
+
(including `ActiveModel` and `ActiveRecord` objects) are supported.
|
8
18
|
|
9
19
|
Serializers know about both a model and the `current_user`, so you can
|
10
20
|
customize serialization based upon whether a user is authorized to see the
|
@@ -13,13 +23,13 @@ content.
|
|
13
23
|
In short, **serializers replace hash-driven development with object-oriented
|
14
24
|
development.**
|
15
25
|
|
16
|
-
# Installing
|
26
|
+
# Installing
|
17
27
|
|
18
28
|
The easiest way to install `ActiveModel::Serializers` is to add it to your
|
19
29
|
`Gemfile`:
|
20
30
|
|
21
31
|
```ruby
|
22
|
-
gem "active_model_serializers"
|
32
|
+
gem "active_model_serializers"
|
23
33
|
```
|
24
34
|
|
25
35
|
Then, install it on the command line:
|
@@ -28,6 +38,16 @@ Then, install it on the command line:
|
|
28
38
|
$ bundle install
|
29
39
|
```
|
30
40
|
|
41
|
+
#### Ruby 1.8 is no longer supported!
|
42
|
+
|
43
|
+
If you must use a ruby 1.8 version (MRI 1.8.7, REE, Rubinius 1.8, or JRuby 1.8), you need to use version 0.8.x.
|
44
|
+
Versions after 0.9.0 do not support ruby 1.8. To specify version 0.8, include this in your Gemfile:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
gem "active_model_serializers", "~> 0.8.0"
|
48
|
+
```
|
49
|
+
|
50
|
+
|
31
51
|
# Creating a Serializer
|
32
52
|
|
33
53
|
The easiest way to create a new serializer is to generate a new resource, which
|
@@ -45,34 +65,11 @@ the serializer generator:
|
|
45
65
|
$ rails g serializer post
|
46
66
|
```
|
47
67
|
|
48
|
-
### Support for POROs
|
49
|
-
|
50
|
-
Currently `ActiveModel::Serializers` adds serialization support to all models
|
51
|
-
that descend from `ActiveRecord` or include `Mongoid::Document`. If you are:
|
52
|
-
|
53
|
-
- using another ORM, or
|
54
|
-
- using objects that are `ActiveModel` compliant but do not descend from
|
55
|
-
`ActiveRecord` *or* include `Mongoid::Document`
|
56
|
-
|
57
|
-
You must add an include statement for `ActiveModel::SerializerSupport` to
|
58
|
-
make models serializable.
|
59
|
-
|
60
|
-
If you also want to make collections serializable, you should include
|
61
|
-
`ActiveModel::ArraySerializerSupport` into your ORM's
|
62
|
-
relation/criteria class.
|
63
|
-
|
64
|
-
Example model (`app/models/avatar.rb`):
|
65
|
-
|
66
|
-
```ruby
|
67
|
-
class Avatar
|
68
|
-
include ActiveModel::SerializerSupport
|
69
|
-
# etc, etc
|
70
|
-
end
|
71
|
-
```
|
68
|
+
### Support for POROs
|
72
69
|
|
73
|
-
|
74
|
-
|
75
|
-
|
70
|
+
Currently `ActiveModel::Serializers` expects objects to implement
|
71
|
+
read\_attribute\_for\_serialization. That's all you need to do to have
|
72
|
+
your POROs supported.
|
76
73
|
|
77
74
|
# ActiveModel::Serializer
|
78
75
|
|
@@ -87,7 +84,7 @@ for a serializer for the object and use it if available.
|
|
87
84
|
class PostsController < ApplicationController
|
88
85
|
def show
|
89
86
|
@post = Post.find(params[:id])
|
90
|
-
render :
|
87
|
+
render json: @post
|
91
88
|
end
|
92
89
|
end
|
93
90
|
```
|
@@ -99,22 +96,11 @@ This also works with `respond_with`, which uses `to_json` under the hood. Also
|
|
99
96
|
note that any options passed to `render :json` will be passed to your
|
100
97
|
serializer and available as `@options` inside.
|
101
98
|
|
102
|
-
To specify a custom serializer for an object,
|
103
|
-
|
104
|
-
#### 1. Specify the serializer in your model:
|
99
|
+
To specify a custom serializer for an object, you can specify the
|
100
|
+
serializer when you render the object:
|
105
101
|
|
106
102
|
```ruby
|
107
|
-
|
108
|
-
def active_model_serializer
|
109
|
-
FancyPostSerializer
|
110
|
-
end
|
111
|
-
end
|
112
|
-
```
|
113
|
-
|
114
|
-
#### 2. Specify the serializer when you render the object:
|
115
|
-
|
116
|
-
```ruby
|
117
|
-
render :json => @post, :serializer => FancyPostSerializer
|
103
|
+
render json: @post, serializer: FancyPostSerializer
|
118
104
|
```
|
119
105
|
|
120
106
|
## Arrays
|
@@ -131,7 +117,7 @@ end
|
|
131
117
|
class PostsController < ApplicationController
|
132
118
|
def index
|
133
119
|
@posts = Post.all
|
134
|
-
render :
|
120
|
+
render json: @posts
|
135
121
|
end
|
136
122
|
end
|
137
123
|
```
|
@@ -152,7 +138,7 @@ By default, the root element is the name of the controller. For example, `PostsC
|
|
152
138
|
generates a root element "posts". To change it:
|
153
139
|
|
154
140
|
```ruby
|
155
|
-
render :
|
141
|
+
render json: @posts, root: "some_posts"
|
156
142
|
```
|
157
143
|
|
158
144
|
You may disable the root element for arrays at the top level, which will result in
|
@@ -169,7 +155,7 @@ root element of the array with any of those methods will produce
|
|
169
155
|
To specify a custom serializer for the items within an array:
|
170
156
|
|
171
157
|
```ruby
|
172
|
-
render :
|
158
|
+
render json: @posts, each_serializer: FancyPostSerializer
|
173
159
|
```
|
174
160
|
|
175
161
|
## Disabling the root element
|
@@ -181,19 +167,17 @@ You have 4 options to disable the root element, each with a slightly different s
|
|
181
167
|
In an initializer:
|
182
168
|
|
183
169
|
```ruby
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
ActiveModel::ArraySerializer.root = false
|
190
|
-
end
|
170
|
+
# Disable for all serializers (except ArraySerializer)
|
171
|
+
ActiveModel::Serializer.root = false
|
172
|
+
|
173
|
+
# Disable for ArraySerializer
|
174
|
+
ActiveModel::ArraySerializer.root = false
|
191
175
|
```
|
192
176
|
|
193
177
|
#### 2. Disable root per render call in your controller
|
194
178
|
|
195
179
|
```ruby
|
196
|
-
render :
|
180
|
+
render json: @posts, root: false
|
197
181
|
```
|
198
182
|
|
199
183
|
#### 3. Subclass the serializer, and specify using it
|
@@ -204,7 +188,7 @@ class CustomArraySerializer < ActiveModel::ArraySerializer
|
|
204
188
|
end
|
205
189
|
|
206
190
|
# controller:
|
207
|
-
render :
|
191
|
+
render json: @posts, serializer: CustomArraySerializer
|
208
192
|
```
|
209
193
|
|
210
194
|
#### 4. Define default_serializer_options in your controller
|
@@ -224,7 +208,7 @@ end
|
|
224
208
|
## Getting the old version
|
225
209
|
|
226
210
|
If you find that your project is already relying on the old rails to_json
|
227
|
-
change `render :json` to `render :
|
211
|
+
change `render :json` to `render json: @your_object.to_json`.
|
228
212
|
|
229
213
|
# Attributes and Associations
|
230
214
|
|
@@ -262,49 +246,57 @@ end
|
|
262
246
|
Within a serializer's methods, you can access the object being
|
263
247
|
serialized as `object`.
|
264
248
|
|
265
|
-
|
266
|
-
authorization context to your serializer. By default, the context
|
267
|
-
is the current user of your application, but this
|
268
|
-
[can be customized](#customizing-scope).
|
269
|
-
|
270
|
-
Serializers will check for the presence of a method named
|
271
|
-
`include_[ATTRIBUTE]?` to determine whether a particular attribute should be
|
272
|
-
included in the output. This is typically used to customize output
|
273
|
-
based on `current_user`. For example:
|
249
|
+
Since this shadows any attribute named `object`, you can include them through `object.object`. For example:
|
274
250
|
|
275
251
|
```ruby
|
276
|
-
class
|
277
|
-
|
252
|
+
class VersionSerializer < ActiveModel::Serializer
|
253
|
+
attribute :version_object, key: :object
|
278
254
|
|
279
|
-
def
|
280
|
-
|
255
|
+
def version_object
|
256
|
+
object.object
|
281
257
|
end
|
282
258
|
end
|
283
259
|
```
|
284
260
|
|
285
|
-
|
286
|
-
|
287
|
-
|
261
|
+
You can also access the `scope` method, which provides an
|
262
|
+
authorization context to your serializer. By default, the context
|
263
|
+
is the current user of your application, but this
|
264
|
+
[can be customized](#customizing-scope).
|
265
|
+
|
266
|
+
Serializers provides a method named `filter`, which should return an array
|
267
|
+
used to determine what attributes and associations should be included in the output.
|
268
|
+
This is typically used to customize output based on `current_user`. For example:
|
288
269
|
|
289
270
|
```ruby
|
290
|
-
class
|
291
|
-
attributes :
|
271
|
+
class PostSerializer < ActiveModel::Serializer
|
272
|
+
attributes :id, :title, :body, :author
|
292
273
|
|
293
|
-
def
|
294
|
-
|
274
|
+
def filter(keys)
|
275
|
+
if scope.admin?
|
276
|
+
keys
|
277
|
+
else
|
278
|
+
keys - [:author]
|
279
|
+
end
|
295
280
|
end
|
296
281
|
end
|
297
282
|
```
|
298
283
|
|
284
|
+
And it's also safe to mutate keys argument by doing keys.delete(:author)
|
285
|
+
in case you want to avoid creating two extra arrays. Note that if you do an
|
286
|
+
in-place modification, you still need to return the modified array.
|
287
|
+
|
299
288
|
If you would like the key in the outputted JSON to be different from its name
|
300
|
-
in ActiveRecord, you can
|
289
|
+
in ActiveRecord, you can declare the attribute with the different name
|
290
|
+
and redefine that method:
|
301
291
|
|
302
292
|
```ruby
|
303
293
|
class PostSerializer < ActiveModel::Serializer
|
304
|
-
|
294
|
+
# look up subject on the model, but use title in the JSON
|
295
|
+
def title
|
296
|
+
object.subject
|
297
|
+
end
|
305
298
|
|
306
|
-
|
307
|
-
attribute :subject, :key => :title
|
299
|
+
attributes :id, :body, :title
|
308
300
|
has_many :comments
|
309
301
|
end
|
310
302
|
```
|
@@ -313,7 +305,7 @@ If you would like to add meta information to the outputted JSON, use the `:meta`
|
|
313
305
|
option:
|
314
306
|
|
315
307
|
```ruby
|
316
|
-
render :
|
308
|
+
render json: @posts, serializer: CustomArraySerializer, meta: {total: 10}
|
317
309
|
```
|
318
310
|
|
319
311
|
The above usage of `:meta` will produce the following:
|
@@ -331,7 +323,7 @@ The above usage of `:meta` will produce the following:
|
|
331
323
|
If you would like to change the meta key name you can use the `:meta_key` option:
|
332
324
|
|
333
325
|
```ruby
|
334
|
-
render :
|
326
|
+
render json: @posts, serializer: CustomArraySerializer, meta: {total: 10}, meta_key: 'meta_object'
|
335
327
|
```
|
336
328
|
|
337
329
|
The above usage of `:meta_key` will produce the following:
|
@@ -346,6 +338,9 @@ The above usage of `:meta_key` will produce the following:
|
|
346
338
|
}
|
347
339
|
```
|
348
340
|
|
341
|
+
When using meta information, your serializer cannot have the `{ root: false }` option, as this would lead to
|
342
|
+
invalid JSON. If you do not have a root key, the meta information will be ignored.
|
343
|
+
|
349
344
|
If you would like direct, low-level control of attribute serialization, you can
|
350
345
|
completely override the `attributes` method to return the hash you need:
|
351
346
|
|
@@ -355,7 +350,7 @@ class PersonSerializer < ActiveModel::Serializer
|
|
355
350
|
|
356
351
|
def attributes
|
357
352
|
hash = super
|
358
|
-
if
|
353
|
+
if scope.admin?
|
359
354
|
hash["ssn"] = object.ssn
|
360
355
|
hash["secret"] = object.mothers_maiden_name
|
361
356
|
end
|
@@ -374,7 +369,7 @@ and use it to serialize the comment.
|
|
374
369
|
By default, serializers simply look up the association on the original object.
|
375
370
|
You can customize this behavior by implementing a method with the name of the
|
376
371
|
association and returning a different Array. Often, you will do this to
|
377
|
-
customize the objects returned based on the current user.
|
372
|
+
customize the objects returned based on the current user (scope).
|
378
373
|
|
379
374
|
```ruby
|
380
375
|
class PostSerializer < ActiveModel::Serializer
|
@@ -383,7 +378,7 @@ class PostSerializer < ActiveModel::Serializer
|
|
383
378
|
|
384
379
|
# only let the user see comments he created.
|
385
380
|
def comments
|
386
|
-
object.comments.where(:
|
381
|
+
object.comments.where(created_by: scope)
|
387
382
|
end
|
388
383
|
end
|
389
384
|
```
|
@@ -396,27 +391,27 @@ class PostSerializer < ActiveModel::Serializer
|
|
396
391
|
attributes :id, :title, :body
|
397
392
|
|
398
393
|
# look up comments, but use +my_comments+ as the key in JSON
|
399
|
-
has_many :comments, :
|
394
|
+
has_many :comments, root: :my_comments
|
400
395
|
end
|
401
396
|
```
|
402
397
|
|
403
|
-
Also, as with attributes, serializers will
|
404
|
-
|
405
|
-
|
398
|
+
Also, as with attributes, serializers will execute a filter method to
|
399
|
+
determine which associations should be included in the output. For
|
400
|
+
example:
|
406
401
|
|
407
402
|
```ruby
|
408
403
|
class PostSerializer < ActiveModel::Serializer
|
409
404
|
attributes :id, :title, :body
|
410
405
|
has_many :comments
|
411
406
|
|
412
|
-
def
|
413
|
-
|
407
|
+
def filter(keys)
|
408
|
+
keys.delete :comments if object.comments_disabled?
|
409
|
+
keys
|
414
410
|
end
|
415
411
|
end
|
416
412
|
```
|
417
413
|
|
418
|
-
|
419
|
-
override `include_associations!` to specify which associations should be included:
|
414
|
+
Or ...
|
420
415
|
|
421
416
|
```ruby
|
422
417
|
class PostSerializer < ActiveModel::Serializer
|
@@ -424,9 +419,10 @@ class PostSerializer < ActiveModel::Serializer
|
|
424
419
|
has_one :author
|
425
420
|
has_many :comments
|
426
421
|
|
427
|
-
def
|
428
|
-
|
429
|
-
|
422
|
+
def filter(keys)
|
423
|
+
keys.delete :author unless scope.admin?
|
424
|
+
keys.delete :comments if object.comments_disabled?
|
425
|
+
keys
|
430
426
|
end
|
431
427
|
end
|
432
428
|
```
|
@@ -434,12 +430,15 @@ end
|
|
434
430
|
You may also use the `:serializer` option to specify a custom serializer class and the `:polymorphic` option to specify an association that is polymorphic (STI), e.g.:
|
435
431
|
|
436
432
|
```ruby
|
437
|
-
has_many :comments, :
|
438
|
-
has_one :reviewer, :
|
433
|
+
has_many :comments, serializer: CommentShortSerializer
|
434
|
+
has_one :reviewer, polymorphic: true
|
439
435
|
```
|
440
436
|
|
441
437
|
Serializers are only concerned with multiplicity, and not ownership. `belongs_to` ActiveRecord associations can be included using `has_one` in your serializer.
|
442
438
|
|
439
|
+
NOTE: polymorphic was removed because was only supported for has\_one
|
440
|
+
associations and is in the TODO list of the project.
|
441
|
+
|
443
442
|
## Embedding Associations
|
444
443
|
|
445
444
|
By default, associations will be embedded inside the serialized object. So if
|
@@ -523,7 +522,7 @@ You can specify that the data be included like this:
|
|
523
522
|
|
524
523
|
```ruby
|
525
524
|
class PostSerializer < ActiveModel::Serializer
|
526
|
-
embed :ids, :
|
525
|
+
embed :ids, include: true
|
527
526
|
|
528
527
|
attributes :id, :title, :body
|
529
528
|
has_many :comments
|
@@ -553,15 +552,19 @@ this:
|
|
553
552
|
}
|
554
553
|
```
|
555
554
|
|
555
|
+
When side-loading data, your serializer cannot have the `{ root: false }` option,
|
556
|
+
as this would lead to invalid JSON. If you do not have a root key, the `include`
|
557
|
+
instruction will be ignored
|
558
|
+
|
556
559
|
You can also specify a different root for the embedded objects than the key
|
557
560
|
used to reference them:
|
558
561
|
|
559
562
|
```ruby
|
560
563
|
class PostSerializer < ActiveModel::Serializer
|
561
|
-
embed :ids, :
|
564
|
+
embed :ids, include: true
|
562
565
|
|
563
566
|
attributes :id, :title, :body
|
564
|
-
has_many :comments, :
|
567
|
+
has_many :comments, key: :comment_ids, root: :comment_objects
|
565
568
|
end
|
566
569
|
```
|
567
570
|
|
@@ -586,10 +589,10 @@ objects:
|
|
586
589
|
|
587
590
|
```ruby
|
588
591
|
class PostSerializer < ActiveModel::Serializer
|
589
|
-
embed :ids, :
|
592
|
+
embed :ids, include: true
|
590
593
|
|
591
594
|
attributes :id, :title, :body
|
592
|
-
has_many :comments, :
|
595
|
+
has_many :comments, embed_key: :external_id
|
593
596
|
end
|
594
597
|
```
|
595
598
|
|
@@ -630,7 +633,7 @@ class ApplicationController < ActionController::Base
|
|
630
633
|
end
|
631
634
|
```
|
632
635
|
|
633
|
-
The above example will also change the scope
|
636
|
+
The above example will also change the scope from `current_user` to
|
634
637
|
`current_admin`.
|
635
638
|
|
636
639
|
Please note that, until now, `serialization_scope` doesn't accept a second
|
@@ -641,7 +644,7 @@ To be clear, it's not possible, yet, to do something like this:
|
|
641
644
|
|
642
645
|
```ruby
|
643
646
|
class SomeController < ApplicationController
|
644
|
-
serialization_scope :current_admin, :
|
647
|
+
serialization_scope :current_admin, except: [:index, :show]
|
645
648
|
end
|
646
649
|
```
|
647
650
|
|
@@ -655,13 +658,13 @@ class CitiesController < ApplicationController
|
|
655
658
|
def index
|
656
659
|
@cities = City.all
|
657
660
|
|
658
|
-
render :
|
661
|
+
render json: @cities, each_serializer: CitySerializer
|
659
662
|
end
|
660
663
|
|
661
664
|
def show
|
662
665
|
@city = City.find(params[:id])
|
663
666
|
|
664
|
-
render :
|
667
|
+
render json: @city, scope: current_admin
|
665
668
|
end
|
666
669
|
end
|
667
670
|
```
|
@@ -670,3 +673,74 @@ Assuming that the `current_admin` method needs to make a query in the database
|
|
670
673
|
for the current user, the advantage of this approach is that, by setting
|
671
674
|
`serialization_scope` to `nil`, the `index` action no longer will need to make
|
672
675
|
that query, only the `show` action will.
|
676
|
+
|
677
|
+
## Testing
|
678
|
+
|
679
|
+
In order to test a Serializer, you can just call `.new` on it, passing the object to serialize:
|
680
|
+
|
681
|
+
### MiniTest
|
682
|
+
|
683
|
+
```ruby
|
684
|
+
class TestPostSerializer < Minitest::Test
|
685
|
+
def setup
|
686
|
+
@serializer = PostSerializer.new Post.new(id: 123, title: 'some title', body: 'some text')
|
687
|
+
end
|
688
|
+
|
689
|
+
def test_special_json_for_api
|
690
|
+
assert_equal '{"post":{"id":123,"title":"some title","body":"some text"}}', @serializer.to_json
|
691
|
+
end
|
692
|
+
```
|
693
|
+
|
694
|
+
### RSpec
|
695
|
+
|
696
|
+
```ruby
|
697
|
+
describe PostSerializer do
|
698
|
+
it "creates special JSON for the API" do
|
699
|
+
serializer = PostSerializer.new Post.new(id: 123, title: 'some title', body: 'some text')
|
700
|
+
expect(serializer.to_json).to eql('{"post":{"id":123,"title":"some title","body":"some text"}}')
|
701
|
+
end
|
702
|
+
end
|
703
|
+
```
|
704
|
+
|
705
|
+
## Caching
|
706
|
+
|
707
|
+
NOTE: This functionality was removed from AMS and it's in the TODO list.
|
708
|
+
We need to re-think and re-design the caching strategy for the next
|
709
|
+
version of AMS.
|
710
|
+
|
711
|
+
To cache a serializer, call `cached` and define a `cache_key` method:
|
712
|
+
|
713
|
+
```ruby
|
714
|
+
class PostSerializer < ActiveModel::Serializer
|
715
|
+
cached # enables caching for this serializer
|
716
|
+
|
717
|
+
attributes :title, :body
|
718
|
+
|
719
|
+
def cache_key
|
720
|
+
[object, scope]
|
721
|
+
end
|
722
|
+
end
|
723
|
+
```
|
724
|
+
|
725
|
+
The caching interface uses `Rails.cache` under the hood.
|
726
|
+
|
727
|
+
# Design and Implementation Guidelines
|
728
|
+
|
729
|
+
## Keep it Simple
|
730
|
+
|
731
|
+
`ActiveModel::Serializers` is capable of producing complex JSON views/large object
|
732
|
+
trees, and it may be tempting to design in this way so that your client can make
|
733
|
+
fewer requests to get data and so that related querying can be optimized.
|
734
|
+
However, keeping things simple in your serializers and controllers may
|
735
|
+
significantly reduce complexity and maintenance over the long-term development
|
736
|
+
of your application. Please consider reducing the complexity of the JSON views
|
737
|
+
you provide via the serializers as you build out your application, so that
|
738
|
+
controllers/services can be more easily reused without a lot of complexity
|
739
|
+
later.
|
740
|
+
|
741
|
+
## Performance
|
742
|
+
|
743
|
+
As you develop your controllers or other code that utilizes serializers, try to
|
744
|
+
avoid n+1 queries by ensuring that data loads in an optimal fashion, e.g. if you
|
745
|
+
are using ActiveRecord, you might want to use query includes or joins as needed
|
746
|
+
to make the data available that the serializer(s) need.
|