active_model_serializers 0.9.8 → 0.10.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +21 -0
  3. data/.travis.yml +27 -0
  4. data/CHANGELOG.md +8 -200
  5. data/CONTRIBUTING.md +23 -12
  6. data/Gemfile +17 -0
  7. data/{MIT-LICENSE → LICENSE.txt} +3 -2
  8. data/README.md +151 -781
  9. data/Rakefile +12 -0
  10. data/active_model_serializers.gemspec +26 -0
  11. data/lib/action_controller/serialization.rb +30 -75
  12. data/lib/active_model/serializer.rb +192 -252
  13. data/lib/active_model/serializer/adapter.rb +87 -0
  14. data/lib/active_model/serializer/adapter/fragment_cache.rb +78 -0
  15. data/lib/active_model/serializer/adapter/json.rb +52 -0
  16. data/lib/active_model/serializer/adapter/json/fragment_cache.rb +15 -0
  17. data/lib/active_model/serializer/adapter/json_api.rb +152 -0
  18. data/lib/active_model/serializer/adapter/json_api/fragment_cache.rb +22 -0
  19. data/lib/active_model/serializer/adapter/null.rb +11 -0
  20. data/lib/active_model/serializer/array_serializer.rb +32 -0
  21. data/lib/active_model/serializer/configuration.rb +13 -0
  22. data/lib/active_model/serializer/fieldset.rb +40 -0
  23. data/lib/active_model/serializer/version.rb +1 -1
  24. data/lib/active_model_serializers.rb +5 -7
  25. data/lib/generators/serializer/USAGE +6 -0
  26. data/lib/{active_model/serializer/generators → generators}/serializer/serializer_generator.rb +8 -8
  27. data/lib/{active_model/serializer/generators → generators}/serializer/templates/serializer.rb +2 -2
  28. data/test/action_controller/adapter_selector_test.rb +51 -0
  29. data/test/action_controller/explicit_serializer_test.rb +110 -0
  30. data/test/action_controller/json_api_linked_test.rb +173 -0
  31. data/test/action_controller/serialization_scope_name_test.rb +63 -0
  32. data/test/action_controller/serialization_test.rb +365 -0
  33. data/test/adapter/fragment_cache_test.rb +27 -0
  34. data/test/adapter/json/belongs_to_test.rb +41 -0
  35. data/test/adapter/json/collection_test.rb +59 -0
  36. data/test/adapter/json/has_many_test.rb +36 -0
  37. data/test/adapter/json_api/belongs_to_test.rb +147 -0
  38. data/test/adapter/json_api/collection_test.rb +89 -0
  39. data/test/adapter/json_api/has_many_embed_ids_test.rb +45 -0
  40. data/test/adapter/json_api/has_many_explicit_serializer_test.rb +98 -0
  41. data/test/adapter/json_api/has_many_test.rb +106 -0
  42. data/test/adapter/json_api/has_one_test.rb +59 -0
  43. data/test/adapter/json_api/linked_test.rb +257 -0
  44. data/test/adapter/json_test.rb +34 -0
  45. data/test/adapter/null_test.rb +25 -0
  46. data/test/adapter_test.rb +43 -0
  47. data/test/array_serializer_test.rb +29 -0
  48. data/test/fixtures/poro.rb +125 -142
  49. data/test/serializers/adapter_for_test.rb +50 -0
  50. data/test/serializers/associations_test.rb +106 -0
  51. data/test/serializers/attribute_test.rb +23 -0
  52. data/test/serializers/attributes_test.rb +28 -0
  53. data/test/serializers/cache_test.rb +128 -0
  54. data/test/serializers/configuration_test.rb +15 -0
  55. data/test/serializers/fieldset_test.rb +26 -0
  56. data/test/serializers/generators_test.rb +59 -0
  57. data/test/serializers/meta_test.rb +78 -0
  58. data/test/serializers/options_test.rb +21 -0
  59. data/test/serializers/serializer_for_test.rb +56 -0
  60. data/test/serializers/urls_test.rb +26 -0
  61. data/test/test_helper.rb +21 -4
  62. metadata +121 -159
  63. data/DESIGN.textile +0 -586
  64. data/lib/action_controller/serialization_test_case.rb +0 -79
  65. data/lib/active_model/array_serializer.rb +0 -68
  66. data/lib/active_model/default_serializer.rb +0 -28
  67. data/lib/active_model/serializable.rb +0 -59
  68. data/lib/active_model/serializable/utils.rb +0 -16
  69. data/lib/active_model/serializer/association.rb +0 -58
  70. data/lib/active_model/serializer/association/has_many.rb +0 -39
  71. data/lib/active_model/serializer/association/has_one.rb +0 -25
  72. data/lib/active_model/serializer/config.rb +0 -31
  73. data/lib/active_model/serializer/generators/resource_override.rb +0 -13
  74. data/lib/active_model/serializer/generators/serializer/USAGE +0 -9
  75. data/lib/active_model/serializer/generators/serializer/scaffold_controller_generator.rb +0 -14
  76. data/lib/active_model/serializer/generators/serializer/templates/controller.rb +0 -93
  77. data/lib/active_model/serializer/railtie.rb +0 -22
  78. data/lib/active_model/serializer_support.rb +0 -5
  79. data/lib/active_model_serializers/model/caching.rb +0 -25
  80. data/test/benchmark/app.rb +0 -60
  81. data/test/benchmark/benchmarking_support.rb +0 -67
  82. data/test/benchmark/bm_active_record.rb +0 -41
  83. data/test/benchmark/setup.rb +0 -75
  84. data/test/benchmark/tmp/miniprofiler/mp_timers_6eqewtfgrhitvq5gqm25 +0 -0
  85. data/test/benchmark/tmp/miniprofiler/mp_timers_8083sx03hu72pxz1a4d0 +0 -0
  86. data/test/benchmark/tmp/miniprofiler/mp_timers_fyz2gsml4z0ph9kpoy1c +0 -0
  87. data/test/benchmark/tmp/miniprofiler/mp_timers_hjry5rc32imd42oxoi48 +0 -0
  88. data/test/benchmark/tmp/miniprofiler/mp_timers_m8fpoz2cvt3g9agz0bs3 +0 -0
  89. data/test/benchmark/tmp/miniprofiler/mp_timers_p92m2drnj1i568u3sta0 +0 -0
  90. data/test/benchmark/tmp/miniprofiler/mp_timers_qg52tpca3uesdfguee9i +0 -0
  91. data/test/benchmark/tmp/miniprofiler/mp_timers_s15t1a6mvxe0z7vjv790 +0 -0
  92. data/test/benchmark/tmp/miniprofiler/mp_timers_x8kal3d17nfds6vp4kcj +0 -0
  93. data/test/benchmark/tmp/miniprofiler/mp_views_127.0.0.1 +0 -0
  94. data/test/fixtures/active_record.rb +0 -96
  95. data/test/fixtures/template.html.erb +0 -1
  96. data/test/integration/action_controller/namespaced_serialization_test.rb +0 -105
  97. data/test/integration/action_controller/serialization_test.rb +0 -287
  98. data/test/integration/action_controller/serialization_test_case_test.rb +0 -71
  99. data/test/integration/active_record/active_record_test.rb +0 -94
  100. data/test/integration/generators/resource_generator_test.rb +0 -26
  101. data/test/integration/generators/scaffold_controller_generator_test.rb +0 -64
  102. data/test/integration/generators/serializer_generator_test.rb +0 -41
  103. data/test/test_app.rb +0 -14
  104. data/test/tmp/app/assets/javascripts/accounts.js +0 -2
  105. data/test/tmp/app/assets/stylesheets/accounts.css +0 -4
  106. data/test/tmp/app/controllers/accounts_controller.rb +0 -2
  107. data/test/tmp/app/helpers/accounts_helper.rb +0 -2
  108. data/test/tmp/app/serializers/account_serializer.rb +0 -3
  109. data/test/tmp/config/routes.rb +0 -1
  110. data/test/unit/active_model/array_serializer/except_test.rb +0 -18
  111. data/test/unit/active_model/array_serializer/key_format_test.rb +0 -18
  112. data/test/unit/active_model/array_serializer/meta_test.rb +0 -53
  113. data/test/unit/active_model/array_serializer/only_test.rb +0 -18
  114. data/test/unit/active_model/array_serializer/options_test.rb +0 -16
  115. data/test/unit/active_model/array_serializer/root_test.rb +0 -102
  116. data/test/unit/active_model/array_serializer/scope_test.rb +0 -24
  117. data/test/unit/active_model/array_serializer/serialization_test.rb +0 -216
  118. data/test/unit/active_model/default_serializer_test.rb +0 -13
  119. data/test/unit/active_model/serializer/associations/build_serializer_test.rb +0 -36
  120. data/test/unit/active_model/serializer/associations_test.rb +0 -49
  121. data/test/unit/active_model/serializer/attributes_test.rb +0 -57
  122. data/test/unit/active_model/serializer/config_test.rb +0 -91
  123. data/test/unit/active_model/serializer/filter_test.rb +0 -69
  124. data/test/unit/active_model/serializer/has_many_polymorphic_test.rb +0 -189
  125. data/test/unit/active_model/serializer/has_many_test.rb +0 -265
  126. data/test/unit/active_model/serializer/has_one_and_has_many_test.rb +0 -27
  127. data/test/unit/active_model/serializer/has_one_polymorphic_test.rb +0 -196
  128. data/test/unit/active_model/serializer/has_one_test.rb +0 -253
  129. data/test/unit/active_model/serializer/key_format_test.rb +0 -25
  130. data/test/unit/active_model/serializer/meta_test.rb +0 -39
  131. data/test/unit/active_model/serializer/options_test.rb +0 -42
  132. data/test/unit/active_model/serializer/root_test.rb +0 -117
  133. data/test/unit/active_model/serializer/scope_test.rb +0 -49
  134. data/test/unit/active_model/serializer/url_helpers_test.rb +0 -35
  135. data/test/unit/active_model/serilizable_test.rb +0 -50
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: e9f526564b9458ceea3d9391ddbf81cf996ff713dbb217bcec1c22931b4cd028
4
- data.tar.gz: ac5641428e5b17ffa605bc7337f8f77000354a2a47f1a5ed7244ab50cdca84b2
2
+ SHA1:
3
+ metadata.gz: e77127a346e9bfdfb4b48152c333394b5c5e2e41
4
+ data.tar.gz: cc4ba7acbb64a83d588e6da78c54ace9e9309734
5
5
  SHA512:
6
- metadata.gz: af47a8298fbc563716f0c7b4a9e0d92b85243ead1b0ccac561703d17f09574a3e65f280adedbb24ee7d65c0634c4ca343c58aa665628ff75d7e220b89025e91d
7
- data.tar.gz: 6974a26799a967fbb8b172092be014deb775909a52cf10cf4e7dc88b5c05c96f6b6acbb3d245f9ad9032c743c2048c1afd8335d3a899c3111f2d6b48015800f7
6
+ metadata.gz: fca71a58180a630765a4628c9202b775fb855c36d517546a6fa122166944cd14d79e968369d7fdabce45c6bd585b55a3e9c17ccd72b8b1287fe8eff0b8507167
7
+ data.tar.gz: dafdf5f8c3f57bdbaf141d05573459bc14f314a0a5bc6a30f94eb8f8d6f2e8d29649ba34187112c27c819536dd77a7983715b066c83283ef1434a8ea333669ff
@@ -0,0 +1,21 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ Vagrantfile
14
+ .vagrant
15
+ rdoc
16
+ spec/reports
17
+ test/tmp
18
+ test/version_tmp
19
+ tmp
20
+ *.swp
21
+ .ruby-version
@@ -0,0 +1,27 @@
1
+ language: ruby
2
+
3
+ sudo: false
4
+
5
+ rvm:
6
+ - 1.9.3
7
+ - 2.0.0
8
+ - 2.1
9
+ - 2.2
10
+ - jruby-19mode
11
+ - rbx-2
12
+ - ruby-head
13
+
14
+ install:
15
+ - bundle install --retry=3
16
+
17
+ env:
18
+ - "RAILS_VERSION=3.2"
19
+ - "RAILS_VERSION=4.0"
20
+ - "RAILS_VERSION=4.1"
21
+ - "RAILS_VERSION=master"
22
+
23
+ matrix:
24
+ allow_failures:
25
+ - rvm: ruby-head
26
+ - env: "RAILS_VERSION=master"
27
+ - env: "RAILS_VERSION=3.2"
@@ -1,200 +1,8 @@
1
- ## 0.09.x
2
-
3
- ### [0-9-stable](https://github.com/rails-api/active_model_serializers/compare/v0.9.8...0-9-stable)
4
-
5
- ### [v0.9.8 (2020-12-10)](https://github.com/rails-api/active_model_serializers/compare/v0.9.7...v0.9.8)
6
-
7
- - [#2373](https://github.com/rails-api/active_model_serializers/pull/2373) Fix Rails 6.0 deprecation warnings. (@supremebeing7)
8
-
9
- ### [v0.9.7 (2017-05-01)](https://github.com/rails-api/active_model_serializers/compare/v0.9.6...v0.9.7)
10
-
11
- - [#2080](https://github.com/rails-api/active_model_serializers/pull/2080) remove `{ payload: nil }` from `!serialize.active_model_serializers` ActiveSupport::Notification. `payload` never had a value. Changes, for example `{ serializer: 'ActiveModel::DefaultSerializer', payload: nil }` to be `{ serializer: 'ActiveModel::DefaultSerializer' }` (@yosiat)
12
-
13
- ### [v0.9.6 (2017-01-10)](https://github.com/rails-api/active_model_serializers/compare/v0.9.5...v0.9.6)
14
-
15
- - [#2008](https://github.com/rails-api/active_model_serializers/pull/2008) Fix warning on Thor. (@kirs)
16
-
17
- ### [v0.9.5 (2016-03-30)](https://github.com/rails-api/active_model_serializers/compare/v0.9.4...v0.9.5)
18
-
19
- - [#1607](https://github.com/rails-api/active_model_serializers/pull/1607) Merge multiple nested associations. (@Hirtenknogger)
20
-
21
- ### [v0.9.4 (2016-01-05)](https://github.com/rails-api/active_model_serializers/compare/v0.9.3...v0.9.4)
22
-
23
- - [#752](https://github.com/rails-api/active_model_serializers/pull/752) Tiny improvement of README 0-9-stable (@basiam)
24
- - [#749](https://github.com/rails-api/active_model_serializers/pull/749) remove trailing whitespace (@shwoodard)
25
- - [#717](https://github.com/rails-api/active_model_serializers/pull/717) fixed issue with rendering Hash which appears in rails 4.2.0.beta4 (@kurko, @greshny)
26
- - [#790](https://github.com/rails-api/active_model_serializers/pull/790) pass context to ArraySerializer (@lanej)
27
- - [#797](https://github.com/rails-api/active_model_serializers/pull/797) Fix and test for #490 (@afn)
28
- - [#813](https://github.com/rails-api/active_model_serializers/pull/813) Allow to define custom serializer for given class (@jtomaszewski)
29
- - [#841](https://github.com/rails-api/active_model_serializers/pull/841) Fix issue with embedding multiple associations under the same root key (@antstorm)
30
- - [#748](https://github.com/rails-api/active_model_serializers/pull/748) Propagate serialization_options across associations (@raphaelpereira)
31
-
32
- ### [v0.9.3 (2015/01/21 20:29 +00:00)](https://github.com/rails-api/active_model_serializers/compare/v0.9.2...v0.9.3)
33
-
34
- Features:
35
- - [#774](https://github.com/rails-api/active_model_serializers/pull/774) Fix nested include attributes (@nhocki)
36
- - [#771](https://github.com/rails-api/active_model_serializers/pull/771) Make linked resource type names consistent with root names (@sweatypitts)
37
- - [#696](https://github.com/rails-api/active_model_serializers/pull/696) Explicitly set serializer for associations (@ggordon)
38
- - [#700](https://github.com/rails-api/active_model_serializers/pull/700) sparse fieldsets (@arenoir)
39
- - [#768](https://github.com/rails-api/active_model_serializers/pull/768) Adds support for `meta` and `meta_key` attribute (@kurko)
40
-
41
- ### [v0.9.2](https://github.com/rails-api/active_model_serializers/compare/v0.9.1...v0.9.2)
42
-
43
- ### [v0.9.1 (2014/12/04 11:54 +00:00)](https://github.com/rails-api/active_model_serializers/compare/v0.9.0...v0.9.1)
44
-
45
- - [#707](https://github.com/rails-api/active_model_serializers/pull/707) A Friendly Note on Which AMS Version to Use (@jherdman)
46
- - [#730](https://github.com/rails-api/active_model_serializers/pull/730) Fixes nested has_many links in JSONAPI (@kurko)
47
- - [#718](https://github.com/rails-api/active_model_serializers/pull/718) Allow overriding the adapter with render option (@ggordon)
48
- - [#720](https://github.com/rails-api/active_model_serializers/pull/720) Rename attribute with :key (0.8.x compatibility) (@ggordon)
49
- - [#728](https://github.com/rails-api/active_model_serializers/pull/728) Use type as key for linked resources (@kurko)
50
- - [#729](https://github.com/rails-api/active_model_serializers/pull/729) Use the new beta build env on Travis (@joshk)
51
- - [#703](https://github.com/rails-api/active_model_serializers/pull/703) Support serializer and each_serializer options in renderer (@ggordon, @mieko)
52
- - [#727](https://github.com/rails-api/active_model_serializers/pull/727) Includes links inside of linked resources (@kurko)
53
- - [#726](https://github.com/rails-api/active_model_serializers/pull/726) Bugfix: include nested has_many associations (@kurko)
54
- - [#722](https://github.com/rails-api/active_model_serializers/pull/722) Fix infinite recursion (@ggordon)
55
- - [#1](https://github.com/rails-api/active_model_serializers/pull/1) Allow for the implicit use of ArraySerializer when :each_serializer is specified (@mieko)
56
- - [#692](https://github.com/rails-api/active_model_serializers/pull/692) Include 'linked' member for json-api collections (@ggordon)
57
- - [#714](https://github.com/rails-api/active_model_serializers/pull/714) Define as_json instead of to_json (@guilleiguaran)
58
- - [#710](https://github.com/rails-api/active_model_serializers/pull/710) JSON-API: Don't include linked section if associations are empty (@guilleiguaran)
59
- - [#711](https://github.com/rails-api/active_model_serializers/pull/711) Fixes rbx gems bundling on TravisCI (@kurko)
60
- - [#709](https://github.com/rails-api/active_model_serializers/pull/709) Add type key when association name is different than object type (@guilleiguaran)
61
- - [#708](https://github.com/rails-api/active_model_serializers/pull/708) Handle correctly null associations (@guilleiguaran)
62
- - [#691](https://github.com/rails-api/active_model_serializers/pull/691) Fix embed option for associations (@jacob-s-son)
63
- - [#689](https://github.com/rails-api/active_model_serializers/pull/689) Fix support for custom root in JSON-API adapter (@guilleiguaran)
64
- - [#685](https://github.com/rails-api/active_model_serializers/pull/685) Serialize ids as strings in JSON-API adapter (@guilleiguaran)
65
- - [#684](https://github.com/rails-api/active_model_serializers/pull/684) Refactor adapters to implement support for array serialization (@guilleiguaran)
66
- - [#682](https://github.com/rails-api/active_model_serializers/pull/682) Include root by default in JSON-API serializers (@guilleiguaran)
67
- - [#625](https://github.com/rails-api/active_model_serializers/pull/625) Add DSL for urls (@JordanFaust)
68
- - [#677](https://github.com/rails-api/active_model_serializers/pull/677) Add support for embed: :ids option for in associations (@guilleiguaran)
69
- - [#681](https://github.com/rails-api/active_model_serializers/pull/681) Check superclasses for Serializers (@quainjn)
70
- - [#680](https://github.com/rails-api/active_model_serializers/pull/680) Add support for root keys (@NullVoxPopuli)
71
- - [#675](https://github.com/rails-api/active_model_serializers/pull/675) Support Rails 4.2.0 (@tricknotes)
72
- - [#667](https://github.com/rails-api/active_model_serializers/pull/667) Require only activemodel instead of full rails (@guilleiguaran)
73
- - [#653](https://github.com/rails-api/active_model_serializers/pull/653) Add "_test" suffix to JsonApi::HasManyTest filename. (@alexgenco)
74
- - [#631](https://github.com/rails-api/active_model_serializers/pull/631) Update build badge URL (@craiglittle)
75
-
76
- ### [v0.9.0](https://github.com/rails-api/active_model_serializers/compare/v0.9.0.alpha1...v0.9.0)
77
-
78
- ### [0.9.0.alpha1 - January 7, 2014](https://github.com/rails-api/active_model_serializers/compare/d72b66d4c...v0.9.0.alpha1)
79
-
80
- ### 0.9.0.pre
81
-
82
- * The following methods were removed
83
- - Model#active\_model\_serializer
84
- - Serializer#include!
85
- - Serializer#include?
86
- - Serializer#attr\_disabled=
87
- - Serializer#cache
88
- - Serializer#perform\_caching
89
- - Serializer#schema (needs more discussion)
90
- - Serializer#attribute
91
- - Serializer#include\_#{name}? (filter method added)
92
- - Serializer#attributes (took a hash)
93
-
94
- * The following things were added
95
- - Serializer#filter method
96
- - CONFIG object
97
-
98
- * Remove support for ruby 1.8 versions.
99
-
100
- * Require rails >= 3.2.
101
-
102
- * Serializers for associations are being looked up in a parent serializer's namespace first. Same with controllers' namespaces.
103
-
104
- * Added a "prefix" option in case you want to use a different version of serializer.
105
-
106
- * Serializers default namespace can be set in `default_serializer_options` and inherited by associations.
107
-
108
- # VERSION 0.9.0.pre
109
-
110
- * The following methods were removed
111
- - Model#active\_model\_serializer
112
- - Serializer#include!
113
- - Serializer#include?
114
- - Serializer#attr\_disabled=
115
- - Serializer#cache
116
- - Serializer#perform\_caching
117
- - Serializer#schema (needs more discussion)
118
- - Serializer#attribute
119
- - Serializer#include\_#{name}? (filter method added)
120
- - Serializer#attributes (took a hash)
121
-
122
- * The following things were added
123
- - Serializer#filter method
124
- - CONFIG object
125
-
126
- * Remove support for ruby 1.8 versions.
127
-
128
- * Require rails >= 3.2.
129
-
130
- * Serializers for associations are being looked up in a parent serializer's namespace first. Same with controllers' namespaces.
131
-
132
- * Added a "prefix" option in case you want to use a different version of serializer.
133
-
134
- * Serializers default namespace can be set in `default_serializer_options` and inherited by associations.
135
-
136
- # VERSION 0.8.1
137
-
138
- * Fix bug whereby a serializer using 'options' would blow up.
139
-
140
- # VERSION 0.8.0
141
-
142
- * Attributes can now have optional types.
143
-
144
- * A new DefaultSerializer ensures that POROs behave the same way as ActiveModels.
145
-
146
- * If you wish to override ActiveRecord::Base#to\_Json, you can now require
147
- 'active\_record/serializer\_override'. We don't recommend you do this, but
148
- many users do, so we've left it optional.
149
-
150
- * Fixed a bug where ActionController wouldn't always have MimeResponds.
151
-
152
- * An optional caching feature allows you to cache JSON & hashes that AMS uses.
153
- Adding 'cached true' to your Serializers will turn on this cache.
154
-
155
- * URL helpers used inside of Engines now work properly.
156
-
157
- * Serializers now can filter attributes with `only` and `except`:
158
-
159
- ```
160
- UserSerializer.new(user, only: [:first_name, :last_name])
161
- UserSerializer.new(user, except: :first_name)
162
- ```
163
-
164
- * Basic Mongoid support. We now include our mixins in the right place.
165
-
166
- * On Ruby 1.8, we now generate an `id` method that properly serializes `id`
167
- columns. See issue #127 for more.
168
-
169
- * Add an alias for `scope` method to be the name of the context. By default
170
- this is `current_user`. The name is automatically set when using
171
- `serialization_scope` in the controller.
172
-
173
- * Pass through serialization options (such as `:include`) when a model
174
- has no serializer defined.
175
-
176
- # VERSION 0.7.0
177
-
178
- * ```embed_key``` option to allow embedding by attributes other than IDs
179
- * Fix rendering nil with custom serializer
180
- * Fix global ```self.root = false```
181
- * Add support for specifying the serializer for an association as a String
182
- * Able to specify keys on the attributes method
183
- * Serializer Reloading via ActiveSupport::DescendantsTracker
184
- * Reduce double map to once; Fixes datamapper eager loading.
185
-
186
- # VERSION 0.6.0
187
-
188
- * Serialize sets properly
189
- * Add root option to ArraySerializer
190
- * Support polymorphic associations
191
- * Support :each_serializer in ArraySerializer
192
- * Add `scope` method to easily access the scope in the serializer
193
- * Fix regression with Rails 3.2.6; add Rails 4 support
194
- * Allow serialization_scope to be disabled with serialization_scope nil
195
- * Array serializer should support pure ruby objects besides serializers
196
-
197
- # VERSION 0.5.0
198
-
199
- * First tagged version
200
- * Changes generators to always generate an ApplicationSerializer
1
+ ### 0.10.0
2
+
3
+ * adds support for `meta` and `meta_key` [@kurko]
4
+ * adds method to override association [adcb99e, @kurko]
5
+ * adds `has_one` attribute for backwards compatibility [@ggordon]
6
+ * updates JSON API support to RC3 [@mateomurphy]
7
+ * adds fragment cache support [@joaomdmoura]
8
+ * adds cache support to attributes and associations [@joaomdmoura]
@@ -1,20 +1,31 @@
1
- Contributing to AMS
2
- ===================
1
+ ## How can I help?
3
2
 
4
- First of all, **thank you**!
3
+ Everyone is encouraged to open issues that are affecting you: bugs, ideas, performance problems – everything helps!
5
4
 
6
- Now, for the details:
5
+ The first place to start is by looking at our [GitHub Issues](https://github.com/rails-api/active_model_serializers/issues).
7
6
 
8
- Please file issues on the [GitHub Issues
9
- list](https://github.com/rails-api/active_model_serializers/issues).
7
+ The vast majority of development is happening under the `master` branch, currently slated for release as `0.10.x`. This is where we would suggest you start.
10
8
 
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).
9
+ Fixing bugs is extraordinarily helpful and requires the least familiarity with AMS. Look for issues labeled [**Needs Bug Verification**](https://github.com/rails-api/active_model_serializers/labels/Needs%20Bug%20Verification) and [**Bug**](https://github.com/rails-api/active_model_serializers/labels/bug).
13
10
 
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.
11
+ We are also actively working to identify tasks under the label [**Good for New Contributors**](https://github.com/rails-api/active_model_serializers/labels/Good%20for%20New%20Contributors). Some bugs are expressly not good for new contributors, so don't expect 100% overlap between the two.
16
12
 
17
- Please include a CHANGELOG with all entries that change behavior.
13
+ If you want to work on new feature development, look for the label [**Feature**](https://github.com/rails-api/active_model_serializers/labels/Feature).
18
14
 
19
- :heart: :sparkling_heart: :heart:
15
+ We are also encouraging comments to substantial changes (larger than bugfixes and simple features) under an "RFC" (Request for Comments) process before we start active development. Look for the [**RFC**](https://github.com/rails-api/active_model_serializers/labels/RFC) label.
20
16
 
17
+ ## Issue Labeling
18
+
19
+ AMS uses a subset of [StandardIssueLabels](https://github.com/wagenet/StandardIssueLabels) for Github Issues. You can [see our labels here](https://github.com/rails-api/active_model_serializers/labels).
20
+
21
+ ## Contributing
22
+
23
+ 1. Fork it ( https://github.com/rails-api/active_model_serializers/fork )
24
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
25
+ 3. Write tests for your feature, or regression tests highlighting a bug
26
+ 4. Write the feature itself, or fix your bug
27
+ 5. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 6. Push to the branch (`git push origin my-new-feature`)
29
+ 7. Create a new Pull Request
30
+
31
+ Remember to squash your commits and rebase off `master`.
data/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in active_model_serializers.gemspec
4
+ gemspec
5
+
6
+ gem "minitest"
7
+
8
+ version = ENV["RAILS_VERSION"] || "4.1"
9
+
10
+ if version == "master"
11
+ gem "rails", github: "rails/rails"
12
+
13
+ # ugh https://github.com/rails/rails/issues/16063#issuecomment-48090125
14
+ gem "arel", github: "rails/arel"
15
+ else
16
+ gem "rails", "~> #{version}.0"
17
+ end
@@ -1,4 +1,6 @@
1
- Copyright (c) 2011-2012 José Valim & Yehuda Katz
1
+ Copyright (c) 2014 Steve Klabnik
2
+
3
+ MIT License
2
4
 
3
5
  Permission is hereby granted, free of charge, to any person obtaining
4
6
  a copy of this software and associated documentation files (the
@@ -18,4 +20,3 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
20
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
21
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
22
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
-
data/README.md CHANGED
@@ -1,956 +1,326 @@
1
- [![Build Status](https://api.travis-ci.org/rails-api/active_model_serializers.png?branch=0-9-stable)](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
-
4
1
  # ActiveModel::Serializers
5
2
 
6
- ## Purpose
7
-
8
- `ActiveModel::Serializers` encapsulates the JSON serialization of objects.
9
- Objects that respond to read\_attribute\_for\_serialization
10
- (including `ActiveModel` and `ActiveRecord` objects) are supported.
11
-
12
- Serializers know about both a model and the `current_user`, so you can
13
- customize serialization based upon whether a user is authorized to see the
14
- content.
15
-
16
- In short, **serializers replace hash-driven development with object-oriented
17
- development.**
18
-
19
- # Installing
20
-
21
- The easiest way to install `ActiveModel::Serializers` is to add it to your
22
- `Gemfile`:
23
-
24
- ```ruby
25
- gem "active_model_serializers"
26
- ```
27
-
28
- Then, install it on the command line:
29
-
30
- ```
31
- $ bundle install
32
- ```
33
-
34
- #### Ruby 1.8 is no longer supported!
35
-
36
- 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.
37
- Versions after 0.9.0 do not support ruby 1.8. To specify version 0.8, include this in your Gemfile:
38
-
39
- ```ruby
40
- gem "active_model_serializers", "~> 0.8.0"
41
- ```
42
-
43
-
44
- # Creating a Serializer
45
-
46
- The easiest way to create a new serializer is to generate a new resource, which
47
- will generate a serializer at the same time:
48
-
49
- ```
50
- $ rails g resource post title:string body:string
51
- ```
52
-
53
- This will generate a serializer in `app/serializers/post_serializer.rb` for
54
- your new model. You can also generate a serializer for an existing model with
55
- the serializer generator:
56
-
57
- ```
58
- $ rails g serializer post
59
- ```
60
-
61
- ### Support for POROs
3
+ [![Build Status](https://travis-ci.org/rails-api/active_model_serializers.svg)](https://travis-ci.org/rails-api/active_model_serializers)
62
4
 
63
- The PORO should include ActiveModel::SerializerSupport. That's all you need to
64
- do to have your POROs supported.
5
+ ActiveModel::Serializers brings convention over configuration to your JSON generation.
65
6
 
66
- For Rails versions before Rails 4 ActiveModel::Serializers expects objects to
67
- implement `read_attribute_for_serialization`.
7
+ AMS does this through two components: **serializers** and **adapters**.
8
+ Serializers describe _which_ attributes and relationships should be serialized.
9
+ Adapters describe _how_ attributes and relationships should be serialized.
68
10
 
69
- # render :json
11
+ # RELEASE CANDIDATE, PLEASE READ
70
12
 
71
- In your controllers, when you use `render :json`, Rails will now first search
72
- for a serializer for the object and use it if available.
73
-
74
- ```ruby
75
- class PostsController < ApplicationController
76
- def show
77
- @post = Post.find(params[:id])
78
- render json: @post
79
- end
80
- end
81
- ```
13
+ This is the master branch of AMS. It will become the `0.10.0` release when it's
14
+ ready. Currently this is a release candidate. This is **not** backward
15
+ compatible with `0.9.0` or `0.8.0`.
82
16
 
83
- In this case, Rails will look for a serializer named `PostSerializer`, and if
84
- it exists, use it to serialize the `Post`.
17
+ `0.10.x` will be based on the `0.8.0` code, but with a more flexible
18
+ architecture. We'd love your help. [Learn how you can help here.](https://github.com/rails-api/active_model_serializers/blob/master/CONTRIBUTING.md)
85
19
 
86
- This also works with `respond_with`, which uses `to_json` under the hood. Also
87
- note that any options passed to `render :json` will be passed to your
88
- serializer and available as `@serialization_options` inside.
20
+ ## Example
89
21
 
90
- To specify a custom serializer for an object, you can specify the
91
- serializer when you render the object:
92
-
93
- ```ruby
94
- render json: @post, serializer: FancyPostSerializer
95
- ```
96
-
97
- ### Use serialization outside of ActionController::Base
98
-
99
- When controller does not inherit from ActionController::Base,
100
- include Serialization module manually:
101
-
102
- ```ruby
103
- class ApplicationController < ActionController::API
104
- include ActionController::Serialization
105
- end
106
- ```
107
-
108
- ## Arrays
109
-
110
- In your controllers, when you use `render :json` for an array of objects, AMS will
111
- use `ActiveModel::ArraySerializer` (included in this project) as the base serializer,
112
- and the individual `Serializer` for the objects contained in that array.
22
+ Given two models, a `Post(title: string, body: text)` and a
23
+ `Comment(name:string, body:text, post_id:integer)`, you will have two
24
+ serializers:
113
25
 
114
26
  ```ruby
115
27
  class PostSerializer < ActiveModel::Serializer
28
+ cache key: 'posts', expires_in: 3.hours
116
29
  attributes :title, :body
117
- end
118
-
119
- class PostsController < ApplicationController
120
- def index
121
- @posts = Post.all
122
- render json: @posts
123
- end
124
- end
125
- ```
126
-
127
- Given the example above, the index action will return
128
-
129
- ```json
130
- {
131
- "posts":
132
- [
133
- { "title": "Post 1", "body": "Hello!" },
134
- { "title": "Post 2", "body": "Goodbye!" }
135
- ]
136
- }
137
- ```
138
-
139
- By default, the root element is the name of the controller. For example, `PostsController`
140
- generates a root element "posts". To change it:
141
30
 
142
- ```ruby
143
- render json: @posts, root: "some_posts"
144
- ```
145
-
146
- You may disable the root element for arrays at the top level, which will result in
147
- more concise json. See the next section for ways on how to do this. Disabling the
148
- root element of the array with any of those methods will produce
149
-
150
- ```json
151
- [
152
- { "title": "Post 1", "body": "Hello!" },
153
- { "title": "Post 2", "body": "Goodbye!" }
154
- ]
155
- ```
156
-
157
- To specify a custom serializer for the items within an array:
158
-
159
- ```ruby
160
- render json: @posts, each_serializer: FancyPostSerializer
161
- ```
162
-
163
- ## Render independently
164
-
165
- By default the setting of serializer is in controller as described above which is the
166
- recommended way. However, there may be cases you need to render the json object elsewhere
167
- say in a helper or a view when controller is only for main object.
168
-
169
- Then you can render the serialized JSON independently.
31
+ has_many :comments
170
32
 
171
- ```ruby
172
- def current_user_as_json_helper
173
- CurrentUserSerializer.new(current_user).to_json
33
+ url :post
174
34
  end
175
35
  ```
176
36
 
177
- You can also render an array of objects using ArraySerializer.
37
+ and
178
38
 
179
39
  ```ruby
180
- def users_array_as_json_helper(users)
181
- ActiveModel::ArraySerializer.new(users, each_serializer: UserSerializer).to_json
182
- end
183
- ```
184
-
185
-
186
- ## Disabling the root element
187
-
188
- You have 4 options to disable the root element, each with a slightly different scope:
189
-
190
- #### 1. Disable root globally for all, or per class
191
-
192
- In an initializer:
193
-
194
- ```ruby
195
- # Disable for all serializers (except ArraySerializer)
196
- ActiveModel::Serializer.root = false
197
-
198
- # Disable for ArraySerializer
199
- ActiveModel::ArraySerializer.root = false
200
- ```
201
-
202
- #### 2. Disable root per render call in your controller
203
-
204
- ```ruby
205
- render json: @posts, root: false
206
- ```
207
-
208
- #### 3. Subclass the serializer, and specify using it
209
-
210
- ```ruby
211
- class CustomArraySerializer < ActiveModel::ArraySerializer
212
- self.root = false
213
- end
214
-
215
- # controller:
216
- render json: @posts, serializer: CustomArraySerializer
217
- ```
40
+ class CommentSerializer < ActiveModel::Serializer
41
+ attributes :name, :body
218
42
 
219
- #### 4. Define default_serializer_options in your controller
43
+ belongs_to :post
220
44
 
221
- If you define `default_serializer_options` method in your controller,
222
- all serializers in actions of this controller and it's children will use them.
223
- One of the options may be `root: false`
224
-
225
- ```ruby
226
- def default_serializer_options
227
- {
228
- root: false
229
- }
45
+ url [:post, :comment]
230
46
  end
231
47
  ```
232
48
 
233
- ## Changing the Key Format
234
-
235
- You can specify that serializers use the lower-camel key format at the config, class or instance level.
49
+ Generally speaking, you as a user of AMS will write (or generate) these
50
+ serializer classes. If you want to use a different adapter, such as a JsonApi, you can
51
+ change this in an initializer:
236
52
 
237
53
  ```ruby
238
-
239
- ActiveModel::Serializer.setup do |config|
240
- config.key_format = :lower_camel
241
- end
242
-
243
- class BlogLowerCamelSerializer < ActiveModel::Serializer
244
- format_keys :lower_camel
245
- end
246
-
247
- BlogSerializer.new(object, key_format: :lower_camel)
54
+ ActiveModel::Serializer.config.adapter = ActiveModel::Serializer::Adapter::JsonApi
248
55
  ```
249
56
 
250
- ## Changing the default association key type
251
-
252
- You can specify that serializers use unsuffixed names as association keys by default.
57
+ or
253
58
 
254
59
  ```ruby
255
- ActiveModel::Serializer.setup do |config|
256
- config.default_key_type = :name
257
- end
60
+ ActiveModel::Serializer.config.adapter = :json_api
258
61
  ```
259
62
 
260
- This will build association keys like `comments` or `author` instead of `comment_ids` or `author_id`.
261
-
262
- ## Getting the old version
263
-
264
- If you find that your project is already relying on the old rails to_json
265
- change `render :json` to `render json: @your_object.to_json`.
63
+ You won't need to implement an adapter unless you wish to use a new format or
64
+ media type with AMS.
266
65
 
267
- # Attributes and Associations
268
-
269
- Once you have a serializer, you can specify which attributes and associations
270
- you would like to include in the serialized form.
66
+ If you would like the key in the outputted JSON to be different from its name in ActiveRecord, you can use the :key option to customize it:
271
67
 
272
68
  ```ruby
273
69
  class PostSerializer < ActiveModel::Serializer
274
- attributes :id, :title, :body
70
+ attributes :id, :body
71
+
72
+ # look up :subject on the model, but use +title+ in the JSON
73
+ attribute :subject, :key => :title
275
74
  has_many :comments
276
75
  end
277
76
  ```
278
77
 
279
- ## Attributes
280
-
281
- For specified attributes, a serializer will look up the attribute on the
282
- object you passed to `render :json`. It uses
283
- `read_attribute_for_serialization`, which `ActiveRecord` objects implement as a
284
- regular attribute lookup.
285
-
286
- Before looking up the attribute on the object, a serializer will check for the
287
- presence of a method with the name of the attribute. This allows serializers to
288
- include properties beyond the simple attributes of the model. For example:
78
+ In your controllers, when you use `render :json`, Rails will now first search
79
+ for a serializer for the object and use it if available.
289
80
 
290
81
  ```ruby
291
- class PersonSerializer < ActiveModel::Serializer
292
- attributes :first_name, :last_name, :full_name
82
+ class PostsController < ApplicationController
83
+ def show
84
+ @post = Post.find(params[:id])
293
85
 
294
- def full_name
295
- "#{object.first_name} #{object.last_name}"
86
+ render json: @post
296
87
  end
297
88
  end
298
89
  ```
299
90
 
300
- Within a serializer's methods, you can access the object being
301
- serialized as `object`.
91
+ In this case, Rails will look for a serializer named `PostSerializer`, and if
92
+ it exists, use it to serialize the `Post`.
302
93
 
303
- Since this shadows any attribute named `object`, you can include them through `object.object`. For example:
94
+ ### Specify a serializer
304
95
 
305
- ```ruby
306
- class VersionSerializer < ActiveModel::Serializer
307
- attributes :version_object
96
+ If you wish to use a serializer other than the default, you can explicitly pass it to the renderer.
308
97
 
309
- def version_object
310
- object.object
311
- end
312
- end
313
- ```
314
-
315
- You can also access the `scope` method, which provides an
316
- authorization context to your serializer. By default, the context
317
- is the current user of your application, but this
318
- [can be customized](#customizing-scope).
319
-
320
- Serializers provide a method named `filter`, which should return an array
321
- used to determine what attributes and associations should be included in the output.
322
- This is typically used to customize output based on `current_user`. For example:
98
+ #### 1. For a resource:
323
99
 
324
100
  ```ruby
325
- class PostSerializer < ActiveModel::Serializer
326
- attributes :id, :title, :body, :author
327
-
328
- def filter(keys)
329
- if scope.admin?
330
- keys
331
- else
332
- keys - [:author]
333
- end
334
- end
335
- end
101
+ render json: @post, serializer: PostPreviewSerializer
336
102
  ```
337
103
 
338
- And it's also safe to mutate keys argument by doing keys.delete(:author)
339
- in case you want to avoid creating two extra arrays. Note that if you do an
340
- in-place modification, you still need to return the modified array.
341
-
342
- ### Alias Attribute
343
- If you would like the key in the outputted JSON to be different from its name
344
- in ActiveRecord, you can declare the attribute with the different name
345
- and redefine that method:
104
+ #### 2. For an array resource:
346
105
 
347
106
  ```ruby
348
- class PostSerializer < ActiveModel::Serializer
349
- # look up subject on the model, but use title in the JSON
350
- def title
351
- object.subject
352
- end
107
+ # Use the default `ArraySerializer`, which will use `each_serializer` to
108
+ # serialize each element
109
+ render json: @posts, each_serializer: PostPreviewSerializer
353
110
 
354
- attributes :id, :body, :title
355
- has_many :comments
356
- end
111
+ # Or, you can explicitly provide the collection serializer as well
112
+ render json: @posts, serializer: PaginatedSerializer, each_serializer: PostPreviewSerializer
357
113
  ```
358
114
 
359
- If you would like to add meta information to the outputted JSON, use the `:meta`
360
- option:
115
+ ### Meta
361
116
 
362
- ```ruby
363
- render json: @posts, serializer: CustomArraySerializer, meta: {total: 10}
364
- ```
117
+ If you want a `meta` attribute in your response, specify it in the `render`
118
+ call:
365
119
 
366
- The above usage of `:meta` will produce the following:
367
-
368
- ```json
369
- {
370
- "meta": { "total": 10 },
371
- "posts": [
372
- { "title": "Post 1", "body": "Hello!" },
373
- { "title": "Post 2", "body": "Goodbye!" }
374
- ]
375
- }
120
+ ```ruby
121
+ render json: @post, meta: { total: 10 }
376
122
  ```
377
123
 
378
- If you would like to change the meta key name you can use the `:meta_key` option:
124
+ The key can be customized using `meta_key` option.
379
125
 
380
126
  ```ruby
381
- render json: @posts, serializer: CustomArraySerializer, meta_object: { total: 10 }, meta_key: :meta_object
127
+ render json: @post, meta: { total: 10 }, meta_key: "custom_meta"
382
128
  ```
383
129
 
384
- The above usage of `:meta_key` will produce the following:
385
-
386
- ```json
387
- {
388
- "meta_object": { "total": 10 },
389
- "posts": [
390
- { "title": "Post 1", "body": "Hello!" },
391
- { "title": "Post 2", "body": "Goodbye!" }
392
- ]
393
- }
394
- ```
130
+ `meta` will only be included in your response if there's a root. For instance,
131
+ it won't be included in array responses.
395
132
 
396
- When using meta information, your serializer cannot have the `{ root: false }` option, as this would lead to
397
- invalid JSON. If you do not have a root key, the meta information will be ignored.
133
+ ### Root key
398
134
 
399
- If you would like direct, low-level control of attribute serialization, you can
400
- completely override the `attributes` method to return the hash you need:
135
+ If you want to define a custom root for your response, specify it in the `render`
136
+ call:
401
137
 
402
138
  ```ruby
403
- class PersonSerializer < ActiveModel::Serializer
404
- attributes :first_name, :last_name
405
-
406
- def attributes
407
- hash = super
408
- if scope.admin?
409
- hash["ssn"] = object.ssn
410
- hash["secret"] = object.mothers_maiden_name
411
- end
412
- hash
413
- end
414
- end
139
+ render json: @post, root: "articles"
415
140
  ```
416
141
 
417
- ## Associations
418
-
419
- For specified associations, the serializer will look up the association and
420
- then serialize each element of the association. For instance, a `has_many
421
- :comments` association will create a new `CommentSerializer` for each comment
422
- and use it to serialize the comment.
142
+ ### Overriding association methods
423
143
 
424
- By default, serializers simply look up the association on the original object.
425
- You can customize this behavior by implementing a method with the name of the
426
- association and returning a different Array. Often, you will do this to
427
- customize the objects returned based on the current user (scope).
144
+ If you want to override any association, you can use:
428
145
 
429
146
  ```ruby
430
147
  class PostSerializer < ActiveModel::Serializer
431
- attributes :id, :title, :body
148
+ attributes :id, :body
149
+
432
150
  has_many :comments
433
151
 
434
- # only let the user see comments he created.
435
152
  def comments
436
- object.comments.where(created_by: scope)
153
+ object.comments.active
437
154
  end
438
155
  end
439
156
  ```
440
157
 
441
- As with attributes, you can change the JSON key that the serializer should
442
- use for a particular association.
158
+ ### Overriding attribute methods
443
159
 
444
- ```ruby
445
- class PostSerializer < ActiveModel::Serializer
446
- attributes :id, :title, :body
447
-
448
- # look up comments, but use +my_comments+ as the key in JSON
449
- has_many :comments, root: :my_comments
450
- end
451
- ```
452
-
453
- Also, as with attributes, serializers will execute a filter method to
454
- determine which associations should be included in the output. For
455
- example:
160
+ If you want to override any attribute, you can use:
456
161
 
457
162
  ```ruby
458
163
  class PostSerializer < ActiveModel::Serializer
459
- attributes :id, :title, :body
164
+ attributes :id, :body
165
+
460
166
  has_many :comments
461
167
 
462
- def filter(keys)
463
- keys.delete :comments if object.comments_disabled?
464
- keys
168
+ def body
169
+ object.body.downcase
465
170
  end
466
171
  end
467
172
  ```
468
173
 
469
- Or ...
174
+ ### Built in Adapters
470
175
 
471
- ```ruby
472
- class PostSerializer < ActiveModel::Serializer
473
- attributes :id, :title, :body
474
- has_one :author
475
- has_many :comments
176
+ #### JSONAPI
476
177
 
477
- def filter(keys)
478
- keys.delete :author unless scope.admin?
479
- keys.delete :comments if object.comments_disabled?
480
- keys
481
- end
482
- end
483
- ```
484
-
485
- 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.:
178
+ This adapter follows RC3 of the format specified in
179
+ [jsonapi.org/format](http://jsonapi.org/format). It will include the associated
180
+ resources in the `"included"` member when the resource names are included in the
181
+ `include` option.
486
182
 
487
183
  ```ruby
488
- has_many :comments, serializer: CommentShortSerializer
489
- has_one :reviewer, polymorphic: true
184
+ render @posts, include: ['authors', 'comments']
185
+ # or
186
+ render @posts, include: 'authors,comments'
490
187
  ```
491
188
 
492
- Serializers are only concerned with multiplicity, and not ownership. `belongs_to` ActiveRecord associations can be included using `has_one` in your serializer.
493
-
494
- ## Embedding Associations
189
+ ## Installation
495
190
 
496
- By default, associations will be embedded inside the serialized object. So if
497
- you have a post, the outputted JSON will look like:
191
+ Add this line to your application's Gemfile:
498
192
 
499
- ```json
500
- {
501
- "post": {
502
- "id": 1,
503
- "title": "New post",
504
- "body": "A body!",
505
- "comments": [
506
- { "id": 1, "body": "what a dumb post" }
507
- ]
508
- }
509
- }
193
+ ```
194
+ gem 'active_model_serializers'
510
195
  ```
511
196
 
512
- This is convenient for simple use-cases, but for more complex clients, it is
513
- better to supply an Array of IDs for the association. This makes your API more
514
- flexible from a performance standpoint and avoids wasteful duplication.
515
-
516
- To embed IDs instead of associations, simply use the `embed` class method:
517
-
518
- ```ruby
519
- class PostSerializer < ActiveModel::Serializer
520
- embed :ids
197
+ And then execute:
521
198
 
522
- attributes :id, :title, :body
523
- has_many :comments
524
- end
525
199
  ```
526
-
527
- Now, any associations will be supplied as an Array of IDs:
528
-
529
- ```json
530
- {
531
- "post": {
532
- "id": 1,
533
- "title": "New post",
534
- "body": "A body!",
535
- "comment_ids": [ 1, 2, 3 ]
536
- }
537
- }
200
+ $ bundle
538
201
  ```
539
202
 
540
- You may also choose to embed the IDs by the association's name underneath a
541
- `key` for the resource. For example, say we want to change `comment_ids`
542
- to `comments` underneath a `links` key:
203
+ ## Creating a Serializer
543
204
 
544
- ```ruby
545
- class PostSerializer < ActiveModel::Serializer
546
- attributes :id, :title, :body
205
+ The easiest way to create a new serializer is to generate a new resource, which
206
+ will generate a serializer at the same time:
547
207
 
548
- has_many :comments, embed: :ids, key: :comments, embed_namespace: :links
549
- end
550
208
  ```
551
-
552
- The JSON will look like this:
553
-
554
- ```json
555
- {
556
- "post": {
557
- "id": 1,
558
- "title": "New post",
559
- "body": "A body!",
560
- "links": {
561
- "comments": [ 1, 2, 3 ]
562
- }
563
- }
564
- }
209
+ $ rails g resource post title:string body:string
565
210
  ```
566
211
 
567
- Alternatively, you can choose to embed only the ids or the associated objects per association:
568
-
569
- ```ruby
570
- class PostSerializer < ActiveModel::Serializer
571
- attributes :id, :title, :body
212
+ This will generate a serializer in `app/serializers/post_serializer.rb` for
213
+ your new model. You can also generate a serializer for an existing model with
214
+ the serializer generator:
572
215
 
573
- has_many :comments, embed: :objects
574
- has_many :tags, embed: :ids
575
- end
576
216
  ```
577
-
578
- The JSON will look like this:
579
-
580
- ```json
581
- {
582
- "post": {
583
- "id": 1,
584
- "title": "New post",
585
- "body": "A body!",
586
- "comments": [
587
- { "id": 1, "body": "what a dumb post" }
588
- ],
589
- "tag_ids": [ 1, 2, 3 ]
590
- }
591
- }
217
+ $ rails g serializer post
592
218
  ```
593
219
 
594
- In addition to supplying an Array of IDs, you may want to side-load the data
595
- alongside the main object. This makes it easier to process the entire package
596
- of data without having to recursively scan the tree looking for embedded
597
- information. It also ensures that associations that are shared between several
598
- objects (like tags), are only delivered once for the entire payload.
599
-
600
- You can specify that the data be included like this:
220
+ The generated seralizer will contain basic `attributes` and
221
+ `has_many`/`has_one`/`belongs_to` declarations, based on the model. For example:
601
222
 
602
223
  ```ruby
603
224
  class PostSerializer < ActiveModel::Serializer
604
- embed :ids, include: true
225
+ attributes :title, :body
605
226
 
606
- attributes :id, :title, :body
607
227
  has_many :comments
608
- end
609
- ```
610
-
611
- Assuming that the comments also `has_many :tags`, you will get a JSON like
612
- this:
613
-
614
- ```json
615
- {
616
- "post": {
617
- "id": 1,
618
- "title": "New post",
619
- "body": "A body!",
620
- "comment_ids": [ 1, 2 ]
621
- },
622
- "comments": [
623
- { "id": 1, "body": "what a dumb post", "tag_ids": [ 1, 2 ] },
624
- { "id": 2, "body": "i liked it", "tag_ids": [ 1, 3 ] },
625
- ],
626
- "tags": [
627
- { "id": 1, "name": "short" },
628
- { "id": 2, "name": "whiny" },
629
- { "id": 3, "name": "happy" }
630
- ]
631
- }
632
- ```
633
-
634
- If you would like to namespace association JSON underneath a certain key in
635
- the root document (say, `linked`), you can specify an `embed_in_root_key`:
636
-
637
- ```ruby
638
- class PostSerializer < ActiveModel::Serializer
639
- embed :ids, include: true, embed_in_root_key: :linked
228
+ has_one :author
640
229
 
641
- attributes: :id, :title, :body
642
- has_many :comments, :tags
230
+ url :post
643
231
  end
644
232
  ```
645
233
 
646
- The above would yield the following JSON document:
647
-
648
- ```json
649
- {
650
- "post": {
651
- "id": 1,
652
- "title": "New post",
653
- "body": "A body!",
654
- "comment_ids": [ 1, 2 ]
655
- },
656
- "linked": {
657
- "comments": [
658
- { "id": 1, "body": "what a dumb post", "tag_ids": [ 1, 2 ] },
659
- { "id": 2, "body": "i liked it", "tag_ids": [ 1, 3 ] },
660
- ],
661
- "tags": [
662
- { "id": 1, "name": "short" },
663
- { "id": 2, "name": "whiny" },
664
- { "id": 3, "name": "happy" }
665
- ]
666
- }
667
- }
668
- ```
669
-
670
- When side-loading data, your serializer cannot have the `{ root: false }` option,
671
- as this would lead to invalid JSON. If you do not have a root key, the `include`
672
- instruction will be ignored
673
-
674
- You can also specify a different root for the embedded objects than the key
675
- used to reference them:
234
+ and
676
235
 
677
236
  ```ruby
678
- class PostSerializer < ActiveModel::Serializer
679
- embed :ids, include: true
680
-
681
- attributes :id, :title, :body
682
- has_many :comments, key: :comment_ids, root: :comment_objects
683
- end
684
- ```
685
-
686
- This would generate JSON that would look like this:
687
-
688
- ```json
689
- {
690
- "post": {
691
- "id": 1,
692
- "title": "New post",
693
- "body": "A body!",
694
- "comment_ids": [ 1 ]
695
- },
696
- "comment_objects": [
697
- { "id": 1, "body": "what a dumb post" }
698
- ]
699
- }
700
- ```
237
+ class CommentSerializer < ActiveModel::Serializer
238
+ attributes :name, :body
701
239
 
702
- You can also specify a different attribute to use rather than the ID of the
703
- objects:
240
+ belongs_to :post_id
704
241
 
705
- ```ruby
706
- class PostSerializer < ActiveModel::Serializer
707
- embed :ids, include: true
708
-
709
- attributes :id, :title, :body
710
- has_many :comments, key: :external_id
242
+ url [:post, :comment]
711
243
  end
712
244
  ```
713
245
 
714
- This would generate JSON that would look like this:
715
-
716
- ```json
717
- {
718
- "post": {
719
- "id": 1,
720
- "title": "New post",
721
- "body": "A body!",
722
- "comment_ids": [ "COMM001" ]
723
- },
724
- "comments": [
725
- { "id": 1, "external_id": "COMM001", "body": "what a dumb post" }
726
- ]
727
- }
728
- ```
729
-
730
- **NOTE**: The `embed :ids` mechanism is primary useful for clients that process
731
- data in bulk and load it into a local store. For these clients, the ability to
732
- easily see all of the data per type, rather than having to recursively scan the
733
- data looking for information, is extremely useful.
734
-
735
- If you are mostly working with the data in simple scenarios and manually making
736
- Ajax requests, you probably just want to use the default embedded behavior.
246
+ The attribute names are a **whitelist** of attributes to be serialized.
737
247
 
248
+ The `has_many`, `has_one`, and `belongs_to` declarations describe relationships between
249
+ resources. By default, when you serialize a `Post`, you will get its `Comment`s
250
+ as well.
738
251
 
739
- ## Embedding Polymorphic Associations
740
-
741
- Because we need both the id and the type to be able to identify a polymorphic associated model, these are serialized in a slightly different format than common ones.
742
-
743
- When embedding entire objects:
252
+ You may also use the `:serializer` option to specify a custom serializer class, for example:
744
253
 
745
254
  ```ruby
746
- class PostSerializer < ActiveModel::Serializer
747
- attributes :id, :title
748
- has_many :attachments, polymorphic: true
749
- end
255
+ has_many :comments, serializer: CommentPreviewSerializer
750
256
  ```
751
257
 
752
- ```json
753
- {
754
- "post": {
755
- "id": 1,
756
- "title": "New post",
757
- "attachments": [
758
- {
759
- "type": "image",
760
- "image": {
761
- "id": 3,
762
- "name": "logo",
763
- "url": "http://images.com/logo.jpg"
764
- }
765
- },
766
- {
767
- "type": "video",
768
- "video": {
769
- "id": 12,
770
- "uid": "XCSSMDFWW",
771
- "source": "youtube"
772
- }
773
- }
774
- ]
775
- }
776
- }
777
- ```
778
-
779
- When embedding ids:
780
-
781
- ```ruby
782
- class PostSerializer < ActiveModel::Serializer
783
- embed :ids
258
+ The `url` declaration describes which named routes to use while generating URLs
259
+ for your JSON. Not every adapter will require URLs.
784
260
 
785
- attributes :id, :title
786
- has_many :attachments, polymorphic: true
787
- end
788
- ```
261
+ ## Caching
789
262
 
790
- ```json
791
- {
792
- "post": {
793
- "id": 1,
794
- "title": "New post",
795
- "attachment_ids": [
796
- {
797
- "type": "image",
798
- "id": 12
799
- },
800
- {
801
- "type": "video",
802
- "id": 3
803
- }
804
- ]
805
- }
806
- }
807
- ```
263
+ To cache a serializer, call ```cache``` and pass its options.
264
+ The options are the same options of ```ActiveSupport::Cache::Store```, plus
265
+ a ```key``` option that will be the prefix of the object cache
266
+ on a pattern ```"#{key}/#{object.id}-#{object.updated_at}"```.
808
267
 
268
+ The cache support is optimized to use the cached object in multiple request. An object cached on an ```show``` request will be reused at the ```index```. If there is a relationship with another cached serializer it will also be created and reused automatically.
809
269
 
810
- ## Customizing Scope
270
+ **[NOTE] Every object is individually cached.**
811
271
 
812
- In a serializer, `current_user` is the current authorization scope which the controller
813
- provides to the serializer when you call `render :json`. By default, this is
814
- `current_user`, but can be customized in your controller by calling
815
- `serialization_scope`:
272
+ **[NOTE] The cache is automatically expired after update an object but it's not deleted.**
816
273
 
817
274
  ```ruby
818
- class ApplicationController < ActionController::Base
819
- serialization_scope :current_admin
820
- end
275
+ cache(options = nil) # options: ```{key, expires_in, compress, force, race_condition_ttl}```
821
276
  ```
822
277
 
823
- The above example will also change the scope from `current_user` to
824
- `current_admin`.
825
-
826
- Please note that, until now, `serialization_scope` doesn't accept a second
827
- object with options for specifying which actions should or should not take a
828
- given scope in consideration.
829
-
830
- To be clear, it's not possible, yet, to do something like this:
278
+ Take the example bellow:
831
279
 
832
280
  ```ruby
833
- class SomeController < ApplicationController
834
- serialization_scope :current_admin, except: [:index, :show]
835
- end
836
- ```
837
-
838
- So, in order to have a fine grained control of what each action should take in
839
- consideration for its scope, you may use something like this:
840
-
841
- ```ruby
842
- class CitiesController < ApplicationController
843
- serialization_scope nil
844
-
845
- def index
846
- @cities = City.all
847
-
848
- render json: @cities, each_serializer: CitySerializer
849
- end
281
+ class PostSerializer < ActiveModel::Serializer
282
+ cache key: 'post', expires_in: 3.hours
283
+ attributes :title, :body
850
284
 
851
- def show
852
- @city = City.find(params[:id])
285
+ has_many :comments
853
286
 
854
- render json: @city, scope: current_admin
855
- end
287
+ url :post
856
288
  end
857
289
  ```
858
290
 
859
- Assuming that the `current_admin` method needs to make a query in the database
860
- for the current user, the advantage of this approach is that, by setting
861
- `serialization_scope` to `nil`, the `index` action no longer will need to make
862
- that query, only the `show` action will.
863
-
864
- ## Testing
865
-
866
- In order to test a Serializer, you can just call `.new` on it, passing the object to serialize:
867
-
868
- ### MiniTest
869
-
870
- ```ruby
871
- class TestPostSerializer < Minitest::Test
872
- def setup
873
- @serializer = PostSerializer.new Post.new(id: 123, title: 'some title', body: 'some text')
874
- end
875
-
876
- def test_special_json_for_api
877
- assert_equal '{"post":{"id":123,"title":"some title","body":"some text"}}', @serializer.to_json
878
- end
879
- ```
291
+ On this example every ```Post``` object will be cached with
292
+ the key ```"post/#{post.id}-#{post.updated_at}"```. You can use this key to expire it as you want,
293
+ but in this case it will be automatically expired after 3 hours.
880
294
 
881
- ### RSpec
295
+ ### Fragmenting Caching
882
296
 
883
- ```ruby
884
- describe PostSerializer do
885
- it "creates special JSON for the API" do
886
- serializer = PostSerializer.new Post.new(id: 123, title: 'some title', body: 'some text')
887
- expect(serializer.to_json).to eql('{"post":{"id":123,"title":"some title","body":"some text"}}')
888
- end
889
- end
890
- ```
297
+ If there is some API endpoint that shouldn't be fully cached, you can still optmise it, using Fragment Cache on the attributes and relationships that you want to cache.
891
298
 
892
- ## Caching
299
+ You can define the attribute by using ```only``` or ```except``` option on cache method.
893
300
 
894
- NOTE: This functionality was removed from AMS and it's in the TODO list.
895
- We need to re-think and re-design the caching strategy for the next
896
- version of AMS.
301
+ **[NOTE] Cache serializers will be used at their relationships**
897
302
 
898
- To cache a serializer, call `cached` and define a `cache_key` method:
303
+ Example:
899
304
 
900
305
  ```ruby
901
306
  class PostSerializer < ActiveModel::Serializer
902
- cached # enables caching for this serializer
903
-
307
+ cache key: 'post', expires_in: 3.hours, only: [:title]
904
308
  attributes :title, :body
905
309
 
906
- def cache_key
907
- [object, scope]
908
- end
909
- end
910
- ```
911
-
912
- The caching interface uses `Rails.cache` under the hood.
913
-
914
- # ApplicationSerializer
915
-
916
- By default, new serializers descend from ActiveModel::Serializer. However, if you wish to share behaviour across your serializers you can create an ApplicationSerializer at ```app/serializers/application_serializer.rb```:
310
+ has_many :comments
917
311
 
918
- ```ruby
919
- class ApplicationSerializer < ActiveModel::Serializer
312
+ url :post
920
313
  end
921
314
  ```
922
315
 
923
- Any newly generated serializers will automatically descend from ApplicationSerializer.
924
-
925
- ```
926
- $ rails g serializer post
927
- ```
928
-
929
- now generates:
930
-
931
- ```ruby
932
- class PostSerializer < ApplicationSerializer
933
- attributes :id
934
- end
935
- ```
316
+ ## Getting Help
936
317
 
937
- # Design and Implementation Guidelines
318
+ If you find a bug, please report an [Issue](https://github.com/rails-api/active_model_serializers/issues/new).
938
319
 
939
- ## Keep it Simple
320
+ If you have a question, please [post to Stack Overflow](http://stackoverflow.com/questions/tagged/active-model-serializers).
940
321
 
941
- `ActiveModel::Serializers` is capable of producing complex JSON views/large object
942
- trees, and it may be tempting to design in this way so that your client can make
943
- fewer requests to get data and so that related querying can be optimized.
944
- However, keeping things simple in your serializers and controllers may
945
- significantly reduce complexity and maintenance over the long-term development
946
- of your application. Please consider reducing the complexity of the JSON views
947
- you provide via the serializers as you build out your application, so that
948
- controllers/services can be more easily reused without a lot of complexity
949
- later.
322
+ Thanks!
950
323
 
951
- ## Performance
324
+ # Contributing
952
325
 
953
- As you develop your controllers or other code that utilizes serializers, try to
954
- avoid n+1 queries by ensuring that data loads in an optimal fashion, e.g. if you
955
- are using ActiveRecord, you might want to use query includes or joins as needed
956
- to make the data available that the serializer(s) need.
326
+ See [CONTRIBUTING.md](https://github.com/rails-api/active_model_serializers/blob/master/CONTRIBUTING.md)