gpi-active_model_serializers 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+
2
+ if RUBY_VERSION =~ /1.9/ # assuming you're running Ruby ~1.9
3
+ Encoding.default_external = Encoding::UTF_8
4
+ Encoding.default_internal = Encoding::UTF_8
5
+ end
6
+
7
+ source 'https://rubygems.org'
8
+
9
+ # Specify gem dependencies in active_model_serializers.gemspec
10
+ gemspec
11
+
12
+ gem "coveralls", require: false
@@ -0,0 +1,9 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'rails', github: 'rails/rails'
6
+
7
+ # Current dependencies of edge rails
8
+ gem 'journey', github: 'rails/journey'
9
+ gem 'activerecord-deprecated_finders' , github: 'rails/activerecord-deprecated_finders'
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2011-2012 José Valim & Yehuda Katz
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
@@ -0,0 +1,716 @@
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) [![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
+
3
+ # Purpose
4
+
5
+ The purpose of `ActiveModel::Serializers` is to provide an object to
6
+ encapsulate serialization of `ActiveModel` objects, including `ActiveRecord`
7
+ objects.
8
+
9
+ Serializers know about both a model and the `current_user`, so you can
10
+ customize serialization based upon whether a user is authorized to see the
11
+ content.
12
+
13
+ In short, **serializers replace hash-driven development with object-oriented
14
+ development.**
15
+
16
+ # Installing
17
+
18
+ The easiest way to install `ActiveModel::Serializers` is to add it to your
19
+ `Gemfile`:
20
+
21
+ ```ruby
22
+ gem "active_model_serializers"
23
+ ```
24
+
25
+ Then, install it on the command line:
26
+
27
+ ```
28
+ $ bundle install
29
+ ```
30
+
31
+ #### Ruby 1.8 is no longer supported!
32
+
33
+ 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.
34
+ Versions after 0.9.0 do not support ruby 1.8. To specify version 0.8, include this in your Gemfile:
35
+
36
+ ```ruby
37
+ gem "active_model_serializers", "~> 0.8.0"
38
+ ```
39
+
40
+
41
+ # Creating a Serializer
42
+
43
+ The easiest way to create a new serializer is to generate a new resource, which
44
+ will generate a serializer at the same time:
45
+
46
+ ```
47
+ $ rails g resource post title:string body:string
48
+ ```
49
+
50
+ This will generate a serializer in `app/serializers/post_serializer.rb` for
51
+ your new model. You can also generate a serializer for an existing model with
52
+ the serializer generator:
53
+
54
+ ```
55
+ $ rails g serializer post
56
+ ```
57
+
58
+ ### Support for POROs and other ORMs.
59
+
60
+ Currently `ActiveModel::Serializers` adds serialization support to all models
61
+ that descend from `ActiveRecord` or include `Mongoid::Document`. If you are
62
+ using another ORM, or if you are using objects that are `ActiveModel`
63
+ compliant but do not descend from `ActiveRecord` or include
64
+ `Mongoid::Document`, you must add an include statement for
65
+ `ActiveModel::SerializerSupport` to make models serializable. If you
66
+ also want to make collections serializable, you should include
67
+ `ActiveModel::ArraySerializerSupport` into your ORM's
68
+ relation/criteria class.
69
+
70
+ # ActiveModel::Serializer
71
+
72
+ All new serializers descend from ActiveModel::Serializer
73
+
74
+ # render :json
75
+
76
+ In your controllers, when you use `render :json`, Rails will now first search
77
+ for a serializer for the object and use it if available.
78
+
79
+ ```ruby
80
+ class PostsController < ApplicationController
81
+ def show
82
+ @post = Post.find(params[:id])
83
+ render json: @post
84
+ end
85
+ end
86
+ ```
87
+
88
+ In this case, Rails will look for a serializer named `PostSerializer`, and if
89
+ it exists, use it to serialize the `Post`.
90
+
91
+ This also works with `respond_with`, which uses `to_json` under the hood. Also
92
+ note that any options passed to `render :json` will be passed to your
93
+ serializer and available as `@options` inside.
94
+
95
+ To specify a custom serializer for an object, there are 2 options:
96
+
97
+ #### 1. Specify the serializer in your model:
98
+
99
+ ```ruby
100
+ class Post < ActiveRecord::Base
101
+ def active_model_serializer
102
+ FancyPostSerializer
103
+ end
104
+ end
105
+ ```
106
+
107
+ #### 2. Specify the serializer when you render the object:
108
+
109
+ ```ruby
110
+ render json: @post, serializer: FancyPostSerializer
111
+ ```
112
+
113
+ ## Arrays
114
+
115
+ In your controllers, when you use `render :json` for an array of objects, AMS will
116
+ use `ActiveModel::ArraySerializer` (included in this project) as the base serializer,
117
+ and the individual `Serializer` for the objects contained in that array.
118
+
119
+ ```ruby
120
+ class PostSerializer < ActiveModel::Serializer
121
+ attributes :title, :body
122
+ end
123
+
124
+ class PostsController < ApplicationController
125
+ def index
126
+ @posts = Post.all
127
+ render json: @posts
128
+ end
129
+ end
130
+ ```
131
+
132
+ Given the example above, the index action will return
133
+
134
+ ```json
135
+ {
136
+ "posts":
137
+ [
138
+ { "title": "Post 1", "body": "Hello!" },
139
+ { "title": "Post 2", "body": "Goodbye!" }
140
+ ]
141
+ }
142
+ ```
143
+
144
+ By default, the root element is the name of the controller. For example, `PostsController`
145
+ generates a root element "posts". To change it:
146
+
147
+ ```ruby
148
+ render json: @posts, root: "some_posts"
149
+ ```
150
+
151
+ You may disable the root element for arrays at the top level, which will result in
152
+ more concise json. See the next section for ways on how to do this. Disabling the
153
+ root element of the array with any of those methods will produce
154
+
155
+ ```json
156
+ [
157
+ { "title": "Post 1", "body": "Hello!" },
158
+ { "title": "Post 2", "body": "Goodbye!" }
159
+ ]
160
+ ```
161
+
162
+ To specify a custom serializer for the items within an array:
163
+
164
+ ```ruby
165
+ render json: @posts, each_serializer: FancyPostSerializer
166
+ ```
167
+
168
+ ## Disabling the root element
169
+
170
+ You have 4 options to disable the root element, each with a slightly different scope:
171
+
172
+ #### 1. Disable root globally for all, or per class
173
+
174
+ In an initializer:
175
+
176
+ ```ruby
177
+ ActiveSupport.on_load(:active_model_serializers) do
178
+ # Disable for all serializers (except ArraySerializer)
179
+ ActiveModel::Serializer.root = false
180
+
181
+ # Disable for ArraySerializer
182
+ ActiveModel::ArraySerializer.root = false
183
+ end
184
+ ```
185
+
186
+ #### 2. Disable root per render call in your controller
187
+
188
+ ```ruby
189
+ render json: @posts, root: false
190
+ ```
191
+
192
+ #### 3. Subclass the serializer, and specify using it
193
+
194
+ ```ruby
195
+ class CustomArraySerializer < ActiveModel::ArraySerializer
196
+ self.root = false
197
+ end
198
+
199
+ # controller:
200
+ render json: @posts, serializer: CustomArraySerializer
201
+ ```
202
+
203
+ #### 4. Define default_serializer_options in your controller
204
+
205
+ If you define `default_serializer_options` method in your controller,
206
+ all serializers in actions of this controller and it's children will use them.
207
+ One of the options may be `root: false`
208
+
209
+ ```ruby
210
+ def default_serializer_options
211
+ {
212
+ root: false
213
+ }
214
+ end
215
+ ```
216
+
217
+ ## Getting the old version
218
+
219
+ If you find that your project is already relying on the old rails to_json
220
+ change `render :json` to `render json: @your_object.to_json`.
221
+
222
+ # Attributes and Associations
223
+
224
+ Once you have a serializer, you can specify which attributes and associations
225
+ you would like to include in the serialized form.
226
+
227
+ ```ruby
228
+ class PostSerializer < ActiveModel::Serializer
229
+ attributes :id, :title, :body
230
+ has_many :comments
231
+ end
232
+ ```
233
+
234
+ ## Attributes
235
+
236
+ For specified attributes, a serializer will look up the attribute on the
237
+ object you passed to `render :json`. It uses
238
+ `read_attribute_for_serialization`, which `ActiveRecord` objects implement as a
239
+ regular attribute lookup.
240
+
241
+ Before looking up the attribute on the object, a serializer will check for the
242
+ presence of a method with the name of the attribute. This allows serializers to
243
+ include properties beyond the simple attributes of the model. For example:
244
+
245
+ ```ruby
246
+ class PersonSerializer < ActiveModel::Serializer
247
+ attributes :first_name, :last_name, :full_name
248
+
249
+ def full_name
250
+ "#{object.first_name} #{object.last_name}"
251
+ end
252
+ end
253
+ ```
254
+
255
+ Within a serializer's methods, you can access the object being
256
+ serialized as `object`.
257
+
258
+ Since this shadows any attribute named `object`, you can include them through `object.object`. For example:
259
+
260
+ ```ruby
261
+ class VersionSerializer < ActiveModel::Serializer
262
+ attribute :version_object, key: :object
263
+
264
+ def version_object
265
+ object.object
266
+ end
267
+ end
268
+ ```
269
+
270
+ You can also access the `current_user` method, which provides an
271
+ authorization context to your serializer. By default, the context
272
+ is the current user of your application, but this
273
+ [can be customized](#customizing-scope).
274
+
275
+ Serializers will check for the presence of a method named
276
+ `include_[ATTRIBUTE]?` to determine whether a particular attribute should be
277
+ included in the output. This is typically used to customize output
278
+ based on `current_user`. For example:
279
+
280
+ ```ruby
281
+ class PostSerializer < ActiveModel::Serializer
282
+ attributes :id, :title, :body, :author
283
+
284
+ def include_author?
285
+ current_user.admin?
286
+ end
287
+ end
288
+ ```
289
+
290
+ The type of a computed attribute (like :full_name above) is not easily
291
+ calculated without some sophisticated static code analysis. To specify the
292
+ type of a computed attribute:
293
+
294
+ ```ruby
295
+ class PersonSerializer < ActiveModel::Serializer
296
+ attributes :first_name, :last_name, {full_name: :string}
297
+
298
+ def full_name
299
+ "#{object.first_name} #{object.last_name}"
300
+ end
301
+ end
302
+ ```
303
+
304
+ If you would like the key in the outputted JSON to be different from its name
305
+ in ActiveRecord, you can use the `:key` option to customize it:
306
+
307
+ ```ruby
308
+ class PostSerializer < ActiveModel::Serializer
309
+ attributes :id, :body
310
+
311
+ # look up :subject on the model, but use +title+ in the JSON
312
+ attribute :subject, key: :title
313
+ has_many :comments
314
+ end
315
+ ```
316
+
317
+ If you would like to add meta information to the outputted JSON, use the `:meta`
318
+ option:
319
+
320
+ ```ruby
321
+ render json: @posts, serializer: CustomArraySerializer, meta: {total: 10}
322
+ ```
323
+
324
+ The above usage of `:meta` will produce the following:
325
+
326
+ ```json
327
+ {
328
+ "meta": { "total": 10 },
329
+ "posts": [
330
+ { "title": "Post 1", "body": "Hello!" },
331
+ { "title": "Post 2", "body": "Goodbye!" }
332
+ ]
333
+ }
334
+ ```
335
+
336
+ If you would like to change the meta key name you can use the `:meta_key` option:
337
+
338
+ ```ruby
339
+ render json: @posts, serializer: CustomArraySerializer, meta: {total: 10}, meta_key: 'meta_object'
340
+ ```
341
+
342
+ The above usage of `:meta_key` will produce the following:
343
+
344
+ ```json
345
+ {
346
+ "meta_object": { "total": 10 },
347
+ "posts": [
348
+ { "title": "Post 1", "body": "Hello!" },
349
+ { "title": "Post 2", "body": "Goodbye!" }
350
+ ]
351
+ }
352
+ ```
353
+
354
+ If you would like direct, low-level control of attribute serialization, you can
355
+ completely override the `attributes` method to return the hash you need:
356
+
357
+ ```ruby
358
+ class PersonSerializer < ActiveModel::Serializer
359
+ attributes :first_name, :last_name
360
+
361
+ def attributes
362
+ hash = super
363
+ if current_user.admin?
364
+ hash["ssn"] = object.ssn
365
+ hash["secret"] = object.mothers_maiden_name
366
+ end
367
+ hash
368
+ end
369
+ end
370
+ ```
371
+
372
+ ## Associations
373
+
374
+ For specified associations, the serializer will look up the association and
375
+ then serialize each element of the association. For instance, a `has_many
376
+ :comments` association will create a new `CommentSerializer` for each comment
377
+ and use it to serialize the comment.
378
+
379
+ By default, serializers simply look up the association on the original object.
380
+ You can customize this behavior by implementing a method with the name of the
381
+ association and returning a different Array. Often, you will do this to
382
+ customize the objects returned based on the current user.
383
+
384
+ ```ruby
385
+ class PostSerializer < ActiveModel::Serializer
386
+ attributes :id, :title, :body
387
+ has_many :comments
388
+
389
+ # only let the user see comments he created.
390
+ def comments
391
+ object.comments.where(created_by: current_user)
392
+ end
393
+ end
394
+ ```
395
+
396
+ As with attributes, you can change the JSON key that the serializer should
397
+ use for a particular association.
398
+
399
+ ```ruby
400
+ class PostSerializer < ActiveModel::Serializer
401
+ attributes :id, :title, :body
402
+
403
+ # look up comments, but use +my_comments+ as the key in JSON
404
+ has_many :comments, key: :my_comments
405
+ end
406
+ ```
407
+
408
+ Also, as with attributes, serializers will check for the presence
409
+ of a method named `include_[ASSOCIATION]?` to determine whether a particular association
410
+ should be included in the output. For example:
411
+
412
+ ```ruby
413
+ class PostSerializer < ActiveModel::Serializer
414
+ attributes :id, :title, :body
415
+ has_many :comments
416
+
417
+ def include_comments?
418
+ !object.comments_disabled?
419
+ end
420
+ end
421
+ ```
422
+
423
+ If you would like lower-level control of association serialization, you can
424
+ override `include_associations!` to specify which associations should be included:
425
+
426
+ ```ruby
427
+ class PostSerializer < ActiveModel::Serializer
428
+ attributes :id, :title, :body
429
+ has_one :author
430
+ has_many :comments
431
+
432
+ def include_associations!
433
+ include! :author if current_user.admin?
434
+ include! :comments unless object.comments_disabled?
435
+ end
436
+ end
437
+ ```
438
+
439
+ 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.:
440
+
441
+ ```ruby
442
+ has_many :comments, serializer: CommentShortSerializer
443
+ has_one :reviewer, polymorphic: true
444
+ ```
445
+
446
+ Serializers are only concerned with multiplicity, and not ownership. `belongs_to` ActiveRecord associations can be included using `has_one` in your serializer.
447
+
448
+ ## Embedding Associations
449
+
450
+ By default, associations will be embedded inside the serialized object. So if
451
+ you have a post, the outputted JSON will look like:
452
+
453
+ ```json
454
+ {
455
+ "post": {
456
+ "id": 1,
457
+ "title": "New post",
458
+ "body": "A body!",
459
+ "comments": [
460
+ { "id": 1, "body": "what a dumb post" }
461
+ ]
462
+ }
463
+ }
464
+ ```
465
+
466
+ This is convenient for simple use-cases, but for more complex clients, it is
467
+ better to supply an Array of IDs for the association. This makes your API more
468
+ flexible from a performance standpoint and avoids wasteful duplication.
469
+
470
+ To embed IDs instead of associations, simply use the `embed` class method:
471
+
472
+ ```ruby
473
+ class PostSerializer < ActiveModel::Serializer
474
+ embed :ids
475
+
476
+ attributes :id, :title, :body
477
+ has_many :comments
478
+ end
479
+ ```
480
+
481
+ Now, any associations will be supplied as an Array of IDs:
482
+
483
+ ```json
484
+ {
485
+ "post": {
486
+ "id": 1,
487
+ "title": "New post",
488
+ "body": "A body!",
489
+ "comment_ids": [ 1, 2, 3 ]
490
+ }
491
+ }
492
+ ```
493
+
494
+ Alternatively, you can choose to embed only the ids or the associated objects per association:
495
+
496
+ ```ruby
497
+ class PostSerializer < ActiveModel::Serializer
498
+ attributes :id, :title, :body
499
+
500
+ has_many :comments, embed: :objects
501
+ has_many :tags, embed: :ids
502
+ end
503
+ ```
504
+
505
+ The JSON will look like this:
506
+
507
+ ```json
508
+ {
509
+ "post": {
510
+ "id": 1,
511
+ "title": "New post",
512
+ "body": "A body!",
513
+ "comments": [
514
+ { "id": 1, "body": "what a dumb post" }
515
+ ],
516
+ "tag_ids": [ 1, 2, 3 ]
517
+ }
518
+ }
519
+ ```
520
+
521
+ In addition to supplying an Array of IDs, you may want to side-load the data
522
+ alongside the main object. This makes it easier to process the entire package
523
+ of data without having to recursively scan the tree looking for embedded
524
+ information. It also ensures that associations that are shared between several
525
+ objects (like tags), are only delivered once for the entire payload.
526
+
527
+ You can specify that the data be included like this:
528
+
529
+ ```ruby
530
+ class PostSerializer < ActiveModel::Serializer
531
+ embed :ids, include: true
532
+
533
+ attributes :id, :title, :body
534
+ has_many :comments
535
+ end
536
+ ```
537
+
538
+ Assuming that the comments also `has_many :tags`, you will get a JSON like
539
+ this:
540
+
541
+ ```json
542
+ {
543
+ "post": {
544
+ "id": 1,
545
+ "title": "New post",
546
+ "body": "A body!",
547
+ "comment_ids": [ 1, 2 ]
548
+ },
549
+ "comments": [
550
+ { "id": 1, "body": "what a dumb post", "tag_ids": [ 1, 2 ] },
551
+ { "id": 2, "body": "i liked it", "tag_ids": [ 1, 3 ] },
552
+ ],
553
+ "tags": [
554
+ { "id": 1, "name": "short" },
555
+ { "id": 2, "name": "whiny" },
556
+ { "id": 3, "name": "happy" }
557
+ ]
558
+ }
559
+ ```
560
+
561
+ You can also specify a different root for the embedded objects than the key
562
+ used to reference them:
563
+
564
+ ```ruby
565
+ class PostSerializer < ActiveModel::Serializer
566
+ embed :ids, include: true
567
+
568
+ attributes :id, :title, :body
569
+ has_many :comments, key: :comment_ids, root: :comment_objects
570
+ end
571
+ ```
572
+
573
+ This would generate JSON that would look like this:
574
+
575
+ ```json
576
+ {
577
+ "post": {
578
+ "id": 1,
579
+ "title": "New post",
580
+ "body": "A body!",
581
+ "comment_ids": [ 1 ]
582
+ },
583
+ "comment_objects": [
584
+ { "id": 1, "body": "what a dumb post" }
585
+ ]
586
+ }
587
+ ```
588
+
589
+ You can also specify a different attribute to use rather than the ID of the
590
+ objects:
591
+
592
+ ```ruby
593
+ class PostSerializer < ActiveModel::Serializer
594
+ embed :ids, include: true
595
+
596
+ attributes :id, :title, :body
597
+ has_many :comments, embed_key: :external_id
598
+ end
599
+ ```
600
+
601
+ This would generate JSON that would look like this:
602
+
603
+ ```json
604
+ {
605
+ "post": {
606
+ "id": 1,
607
+ "title": "New post",
608
+ "body": "A body!",
609
+ "comment_ids": [ "COMM001" ]
610
+ },
611
+ "comments": [
612
+ { "id": 1, "external_id": "COMM001", "body": "what a dumb post" }
613
+ ]
614
+ }
615
+ ```
616
+
617
+ **NOTE**: The `embed :ids` mechanism is primary useful for clients that process
618
+ data in bulk and load it into a local store. For these clients, the ability to
619
+ easily see all of the data per type, rather than having to recursively scan the
620
+ data looking for information, is extremely useful.
621
+
622
+ If you are mostly working with the data in simple scenarios and manually making
623
+ Ajax requests, you probably just want to use the default embedded behavior.
624
+
625
+ ## Customizing Scope
626
+
627
+ In a serializer, `current_user` is the current authorization scope which the controller
628
+ provides to the serializer when you call `render :json`. By default, this is
629
+ `current_user`, but can be customized in your controller by calling
630
+ `serialization_scope`:
631
+
632
+ ```ruby
633
+ class ApplicationController < ActionController::Base
634
+ serialization_scope :current_admin
635
+ end
636
+ ```
637
+
638
+ The above example will also change the scope name from `current_user` to
639
+ `current_admin`.
640
+
641
+ Please note that, until now, `serialization_scope` doesn't accept a second
642
+ object with options for specifying which actions should or should not take a
643
+ given scope in consideration.
644
+
645
+ To be clear, it's not possible, yet, to do something like this:
646
+
647
+ ```ruby
648
+ class SomeController < ApplicationController
649
+ serialization_scope :current_admin, except: [:index, :show]
650
+ end
651
+ ```
652
+
653
+ So, in order to have a fine grained control of what each action should take in
654
+ consideration for its scope, you may use something like this:
655
+
656
+ ```ruby
657
+ class CitiesController < ApplicationController
658
+ serialization_scope nil
659
+
660
+ def index
661
+ @cities = City.all
662
+
663
+ render json: @cities, each_serializer: CitySerializer
664
+ end
665
+
666
+ def show
667
+ @city = City.find(params[:id])
668
+
669
+ render json: @city, scope: current_admin, scope_name: :current_admin
670
+ end
671
+ end
672
+ ```
673
+
674
+ Assuming that the `current_admin` method needs to make a query in the database
675
+ for the current user, the advantage of this approach is that, by setting
676
+ `serialization_scope` to `nil`, the `index` action no longer will need to make
677
+ that query, only the `show` action will.
678
+
679
+ ## Caching
680
+
681
+ To cache a serializer, call `cached` and define a `cache_key` method:
682
+
683
+ ```ruby
684
+ class PostSerializer < ActiveModel::Serializer
685
+ cached # enables caching for this serializer
686
+
687
+ attributes :title, :body
688
+
689
+ def cache_key
690
+ [object, current_user]
691
+ end
692
+ end
693
+ ```
694
+
695
+ The caching interface uses `Rails.cache` under the hood.
696
+
697
+ # Design and Implementation
698
+
699
+ ## Keep it Simple
700
+
701
+ ActiveModel::Serializers is capable of producing complex JSON views/large object
702
+ trees, and it may be tempting to design in this way so that your client can make
703
+ fewer requests to get data and so that related querying can be optimized.
704
+ However, keeping things simple in your serializers and controllers may
705
+ significantly reduce complexity and maintenance over the long-term development
706
+ of your application. Please consider reducing the complexity of the JSON views
707
+ you provide via the serializers as you build out your application, so that
708
+ controllers/services can be more easily reused without a lot of complexity
709
+ later.
710
+
711
+ ## Performance
712
+
713
+ As you develop your controllers or other code that utilizes serializers, try to
714
+ avoid n+1 queries by ensuring that data loads in an optimal fashion, e.g. if you
715
+ are using ActiveRecord, you might want to use query includes or joins as needed
716
+ to make the data available that the serializer(s) need.