active_model_serializers 0.8.4 → 0.9.0.alpha1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
[![Build Status](https://api.travis-ci.org/rails-api/active_model_serializers.png)](https://travis-ci.org/rails-api/active_model_serializers)
|
1
|
+
[![Build Status](https://api.travis-ci.org/rails-api/active_model_serializers.png)](https://travis-ci.org/rails-api/active_model_serializers)
|
2
|
+
[![Code Climate](https://codeclimate.com/github/rails-api/active_model_serializers.png)](https://codeclimate.com/github/rails-api/active_model_serializers)
|
3
|
+
[![Coverage Status](https://coveralls.io/repos/rails-api/active_model_serializers/badge.png?branch=master)](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.
|