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.
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.