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.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -45
  3. data/CONTRIBUTING.md +20 -0
  4. data/DESIGN.textile +4 -4
  5. data/{MIT-LICENSE.txt → MIT-LICENSE} +0 -0
  6. data/README.md +187 -113
  7. data/lib/action_controller/serialization.rb +30 -16
  8. data/lib/active_model/array_serializer.rb +36 -82
  9. data/lib/active_model/default_serializer.rb +22 -0
  10. data/lib/active_model/serializable.rb +25 -0
  11. data/lib/active_model/serializer.rb +126 -447
  12. data/lib/active_model/serializer/associations.rb +53 -211
  13. data/lib/active_model/serializer/config.rb +31 -0
  14. data/lib/active_model/serializer/generators/resource_override.rb +13 -0
  15. data/lib/{generators → active_model/serializer/generators}/serializer/USAGE +0 -0
  16. data/lib/active_model/serializer/generators/serializer/scaffold_controller_generator.rb +14 -0
  17. data/lib/active_model/serializer/generators/serializer/serializer_generator.rb +37 -0
  18. data/lib/active_model/serializer/generators/serializer/templates/controller.rb +93 -0
  19. data/lib/active_model/serializer/generators/serializer/templates/serializer.rb +8 -0
  20. data/lib/active_model/serializer/railtie.rb +10 -0
  21. data/lib/active_model/{serializers → serializer}/version.rb +1 -1
  22. data/lib/active_model/serializer_support.rb +5 -0
  23. data/lib/active_model_serializers.rb +7 -86
  24. data/test/coverage_setup.rb +15 -0
  25. data/test/fixtures/active_record.rb +92 -0
  26. data/test/fixtures/poro.rb +64 -0
  27. data/test/integration/action_controller/serialization_test.rb +234 -0
  28. data/test/integration/active_record/active_record_test.rb +77 -0
  29. data/test/integration/generators/resource_generator_test.rb +26 -0
  30. data/test/integration/generators/scaffold_controller_generator_test.rb +67 -0
  31. data/test/integration/generators/serializer_generator_test.rb +41 -0
  32. data/test/test_app.rb +11 -0
  33. data/test/test_helper.rb +7 -41
  34. data/test/tmp/app/serializers/account_serializer.rb +3 -0
  35. data/test/unit/active_model/array_serializer/meta_test.rb +53 -0
  36. data/test/unit/active_model/array_serializer/root_test.rb +102 -0
  37. data/test/unit/active_model/array_serializer/scope_test.rb +24 -0
  38. data/test/unit/active_model/array_serializer/serialization_test.rb +83 -0
  39. data/test/unit/active_model/default_serializer_test.rb +13 -0
  40. data/test/unit/active_model/serializer/associations/build_serializer_test.rb +21 -0
  41. data/test/unit/active_model/serializer/associations_test.rb +19 -0
  42. data/test/unit/active_model/serializer/attributes_test.rb +41 -0
  43. data/test/unit/active_model/serializer/config_test.rb +86 -0
  44. data/test/unit/active_model/serializer/filter_test.rb +49 -0
  45. data/test/unit/active_model/serializer/has_many_test.rb +173 -0
  46. data/test/unit/active_model/serializer/has_one_test.rb +151 -0
  47. data/test/unit/active_model/serializer/meta_test.rb +39 -0
  48. data/test/unit/active_model/serializer/root_test.rb +117 -0
  49. data/test/unit/active_model/serializer/scope_test.rb +49 -0
  50. metadata +78 -74
  51. data/.gitignore +0 -18
  52. data/.travis.yml +0 -34
  53. data/Gemfile +0 -38
  54. data/Rakefile +0 -22
  55. data/active_model_serializers.gemspec +0 -24
  56. data/appveyor.yml +0 -27
  57. data/bench/perf.rb +0 -43
  58. data/cruft.md +0 -19
  59. data/lib/active_record/serializer_override.rb +0 -16
  60. data/lib/generators/resource_override.rb +0 -13
  61. data/lib/generators/serializer/serializer_generator.rb +0 -42
  62. data/lib/generators/serializer/templates/serializer.rb +0 -19
  63. data/test/array_serializer_test.rb +0 -75
  64. data/test/association_test.rb +0 -592
  65. data/test/caching_test.rb +0 -177
  66. data/test/generators_test.rb +0 -85
  67. data/test/no_serialization_scope_test.rb +0 -34
  68. data/test/serialization_scope_name_test.rb +0 -67
  69. data/test/serialization_test.rb +0 -396
  70. data/test/serializer_support_test.rb +0 -51
  71. data/test/serializer_test.rb +0 -1466
  72. data/test/test_fakes.rb +0 -218
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6a3bbd628ea9a29ba5746a2d18be35b679992e82
4
- data.tar.gz: f8b574ecfb45e609b89beba0f7d729e22bbe1fe9
3
+ metadata.gz: aeb402f8407aece224529052410e2ad33485d7eb
4
+ data.tar.gz: db4621bc2e62921b75a8e02e77b30e4782951b1a
5
5
  SHA512:
6
- metadata.gz: 59beee726674129f3fa5445858efc7b7c4ca7eefe28bb2923f7a975196406e17daab06a9e29ecbc4afdeb438cb9d214a277db1ff44b966521d8aab14d99af541
7
- data.tar.gz: a392e8ebfc339b793844fc3140f03d57d05d4ce6c2e4aaef80290dbfa0b84321b35fbaecacf077560177c91645a6af87a6827184e91678c7fc89489a14551f06
6
+ metadata.gz: 5496e9420a975333a78f239eb2bbeb680f4240ec22e1bdbbe989fceb480325e14fbd96ab706510f0b0297b8317d85298451b034eabb5f1e67627e03bd0aa5c57
7
+ data.tar.gz: 2320ddcf2bf5c13028669dabc470331008de7e3fe79bf3f4ffb4d70df701731061541ccfc4ed57160dc520b8637e02e75b8510bfb6c72470be4ffd2603618be1
data/CHANGELOG.md CHANGED
@@ -1,46 +1,42 @@
1
- # UNRELEASED
2
-
3
- ### v0.8.4 (2017-09-19)
4
-
5
- - [#1675](https://github.com/rails-api/active_model_serializers/pull/1675) Fix memory leak with :scope_name.
6
- Supplying :scope_name causes `ActiveModel::Serializer#initialize` to
7
- define a method on the class, which retains a reference to the
8
- serializer instance. (@Botje)
9
- - [#1276](https://github.com/rails-api/active_model_serializers/pull/1276) Fix serializers were never including associations on cache hits (@kieran)
10
- - [#1503](https://github.com/rails-api/active_model_serializers/pull/1503) Add documentation with example to `README` for POROs and alternative ORMs (@feministy)
11
- - [#1376](https://github.com/rails-api/active_model_serializers/pull/1376) Test against Rails >= 4.0, Ruby >= 1.9.3 and remove Ruby 1.8 and 1.9.2 support (@bf4, @mhuggins)
12
-
13
- ### v0.8.3 (2014-12-10)
14
- - [#753](https://github.com/rails-api/active_model_serializers/pull/753) Test against Ruby 2.2 on Travis CI (@tricknotes)
15
- - [#745](https://github.com/rails-api/active_model_serializers/pull/745) Missing a word (@jockee)
16
-
17
- ### v0.8.2 (2014/09/01 21:00 +00:00)
18
- - [#612](https://github.com/rails-api/active_model_serializers/pull/612) Feature/adapter (@bolshakov)
19
- * adds adapters pattern
20
- - [#615](https://github.com/rails-api/active_model_serializers/pull/615) Rails does not support const_defined? in development mode (@tpitale)
21
- - [#613](https://github.com/rails-api/active_model_serializers/pull/613) README: typo fix on attributes (@spk)
22
- - [#614](https://github.com/rails-api/active_model_serializers/pull/614) Fix rails 4.0.x build. (@arthurnn)
23
- - [#610](https://github.com/rails-api/active_model_serializers/pull/610) ArraySerializer (@bolshakov)
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
- ### 0.8.0 (May 5, 2013)
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#to_Json, you can now require
38
- 'active_record/serializer_override'. We don't recommend you do this, but
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 optinal caching feature allows you to cache JSON & hashes that AMS uses.
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
- ## [0.7.0 (March 6, 2013)](https://github.com/rails-api/active_model_serializers/commit/fabdc621ff97fbeca317f6301973dd4564b9e695)
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
- ## 0.6.0 (October 22, 2012)
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
- ## 0.05.x
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, :key => :posts
362
- has_one :owned_account, :key => :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, :key => :posts, :serializer => CustomPostSerializer
374
- has_one :owne_account, :key => :account, :serializer => PrivateAccountSerializer
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) [![Code Climate](https://codeclimate.com/github/rails-api/active_model_serializers.png)](https://codeclimate.com/github/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
- # Purpose
5
+ # ActiveModel::Serializers
4
6
 
5
- The purpose of `ActiveModel::Serializers` is to provide an object to
6
- encapsulate serialization of `ActiveModel` objects, including `ActiveRecord`
7
- objects.
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 Serializers
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", "~> 0.8.0"
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 and other ORMs.
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
- If your classes follow the naming conventions prescribed by `ActiveModel`,
74
- you don't need to do anything different in your controller to render the
75
- serialized json.
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 :json => @post
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, there are 2 options:
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
- class Post < ActiveRecord::Base
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 :json => @posts
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 :json => @posts, :root => "some_posts"
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 :json => @posts, :each_serializer => FancyPostSerializer
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
- ActiveSupport.on_load(:active_model_serializers) do
185
- # Disable for all serializers (except ArraySerializer)
186
- ActiveModel::Serializer.root = false
187
-
188
- # Disable for ArraySerializer
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 :json => @posts, :root => false
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 :json => @posts, :serializer => CustomArraySerializer
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 :json => @your_object.to_json`.
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
- You can also access the `current_user` method, which provides an
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 PostSerializer < ActiveModel::Serializer
277
- attributes :id, :title, :body, :author
252
+ class VersionSerializer < ActiveModel::Serializer
253
+ attribute :version_object, key: :object
278
254
 
279
- def include_author?
280
- current_user.admin?
255
+ def version_object
256
+ object.object
281
257
  end
282
258
  end
283
259
  ```
284
260
 
285
- The type of a computed attribute (like :full_name above) is not easily
286
- calculated without some sophisticated static code analysis. To specify the
287
- type of a computed attribute:
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 PersonSerializer < ActiveModel::Serializer
291
- attributes :first_name, :last_name, {:full_name => :string}
271
+ class PostSerializer < ActiveModel::Serializer
272
+ attributes :id, :title, :body, :author
292
273
 
293
- def full_name
294
- "#{object.first_name} #{object.last_name}"
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 use the `:key` option to customize it:
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
- attributes :id, :body
294
+ # look up subject on the model, but use title in the JSON
295
+ def title
296
+ object.subject
297
+ end
305
298
 
306
- # look up :subject on the model, but use +title+ in the JSON
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 :json => @posts, :serializer => CustomArraySerializer, :meta => {:total => 10}
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 :json => @posts, :serializer => CustomArraySerializer, :meta => {:total => 10}, :meta_key => 'meta_object'
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 current_user.admin?
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(:created_by => current_user)
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, :key => :my_comments
394
+ has_many :comments, root: :my_comments
400
395
  end
401
396
  ```
402
397
 
403
- Also, as with attributes, serializers will check for the presence
404
- of a method named `include_[ASSOCIATION]?` to determine whether a particular association
405
- should be included in the output. For example:
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 include_comments?
413
- !object.comments_disabled?
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
- If you would like lower-level control of association serialization, you can
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 include_associations!
428
- include! :author if current_user.admin?
429
- include! :comments unless object.comments_disabled?
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, :serializer => CommentShortSerializer
438
- has_one :reviewer, :polymorphic => true
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, :include => true
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, :include => true
564
+ embed :ids, include: true
562
565
 
563
566
  attributes :id, :title, :body
564
- has_many :comments, :key => :comment_ids, :root => :comment_objects
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, :include => true
592
+ embed :ids, include: true
590
593
 
591
594
  attributes :id, :title, :body
592
- has_many :comments, :embed_key => :external_id
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 name from `current_user` to
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, :except => [:index, :show]
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 :json => @cities, :each_serializer => CitySerializer
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 :json => @city, :scope => current_admin, :scope_name => :current_admin
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.