active_model_serializers 0.8.3 → 0.10.0

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 (232) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE.md +29 -0
  3. data/.github/PULL_REQUEST_TEMPLATE.md +15 -0
  4. data/.gitignore +17 -0
  5. data/.rubocop.yml +104 -0
  6. data/.rubocop_todo.yml +167 -0
  7. data/.simplecov +110 -0
  8. data/.travis.yml +39 -24
  9. data/CHANGELOG.md +465 -6
  10. data/CONTRIBUTING.md +105 -0
  11. data/Gemfile +50 -1
  12. data/{MIT-LICENSE.txt → MIT-LICENSE} +3 -2
  13. data/README.md +102 -590
  14. data/Rakefile +93 -8
  15. data/active_model_serializers.gemspec +65 -23
  16. data/appveyor.yml +24 -0
  17. data/bin/bench +171 -0
  18. data/bin/bench_regression +316 -0
  19. data/bin/serve_benchmark +39 -0
  20. data/docs/ARCHITECTURE.md +126 -0
  21. data/docs/README.md +40 -0
  22. data/docs/STYLE.md +58 -0
  23. data/docs/general/adapters.md +245 -0
  24. data/docs/general/caching.md +52 -0
  25. data/docs/general/configuration_options.md +100 -0
  26. data/docs/general/deserialization.md +100 -0
  27. data/docs/general/getting_started.md +133 -0
  28. data/docs/general/instrumentation.md +40 -0
  29. data/docs/general/key_transforms.md +40 -0
  30. data/docs/general/logging.md +14 -0
  31. data/docs/general/rendering.md +255 -0
  32. data/docs/general/serializers.md +372 -0
  33. data/docs/how-open-source-maintained.jpg +0 -0
  34. data/docs/howto/add_pagination_links.md +139 -0
  35. data/docs/howto/add_root_key.md +51 -0
  36. data/docs/howto/outside_controller_use.md +58 -0
  37. data/docs/howto/passing_arbitrary_options.md +27 -0
  38. data/docs/howto/serialize_poro.md +32 -0
  39. data/docs/howto/test.md +152 -0
  40. data/docs/integrations/ember-and-json-api.md +112 -0
  41. data/docs/integrations/grape.md +19 -0
  42. data/docs/jsonapi/errors.md +56 -0
  43. data/docs/jsonapi/schema/schema.json +366 -0
  44. data/docs/jsonapi/schema.md +151 -0
  45. data/docs/rfcs/0000-namespace.md +106 -0
  46. data/docs/rfcs/template.md +15 -0
  47. data/lib/action_controller/serialization.rb +31 -36
  48. data/lib/active_model/serializable_resource.rb +11 -0
  49. data/lib/active_model/serializer/adapter/attributes.rb +15 -0
  50. data/lib/active_model/serializer/adapter/base.rb +16 -0
  51. data/lib/active_model/serializer/adapter/json.rb +15 -0
  52. data/lib/active_model/serializer/adapter/json_api.rb +15 -0
  53. data/lib/active_model/serializer/adapter/null.rb +15 -0
  54. data/lib/active_model/serializer/adapter.rb +24 -0
  55. data/lib/active_model/serializer/array_serializer.rb +9 -0
  56. data/lib/active_model/serializer/association.rb +19 -0
  57. data/lib/active_model/serializer/associations.rb +87 -220
  58. data/lib/active_model/serializer/attribute.rb +25 -0
  59. data/lib/active_model/serializer/attributes.rb +82 -0
  60. data/lib/active_model/serializer/belongs_to_reflection.rb +10 -0
  61. data/lib/active_model/serializer/caching.rb +333 -0
  62. data/lib/active_model/serializer/collection_reflection.rb +7 -0
  63. data/lib/active_model/serializer/collection_serializer.rb +64 -0
  64. data/lib/active_model/serializer/configuration.rb +35 -0
  65. data/lib/active_model/serializer/error_serializer.rb +10 -0
  66. data/lib/active_model/serializer/errors_serializer.rb +27 -0
  67. data/lib/active_model/serializer/field.rb +90 -0
  68. data/lib/active_model/serializer/fieldset.rb +31 -0
  69. data/lib/active_model/serializer/has_many_reflection.rb +10 -0
  70. data/lib/active_model/serializer/has_one_reflection.rb +10 -0
  71. data/lib/active_model/serializer/include_tree.rb +111 -0
  72. data/lib/active_model/serializer/links.rb +35 -0
  73. data/lib/active_model/serializer/lint.rb +146 -0
  74. data/lib/active_model/serializer/meta.rb +29 -0
  75. data/lib/active_model/serializer/null.rb +17 -0
  76. data/lib/active_model/serializer/reflection.rb +147 -0
  77. data/lib/active_model/serializer/singular_reflection.rb +7 -0
  78. data/lib/active_model/serializer/type.rb +25 -0
  79. data/lib/active_model/{serializers → serializer}/version.rb +1 -1
  80. data/lib/active_model/serializer.rb +158 -481
  81. data/lib/active_model_serializers/adapter/attributes.rb +76 -0
  82. data/lib/active_model_serializers/adapter/base.rb +83 -0
  83. data/lib/active_model_serializers/adapter/json.rb +21 -0
  84. data/lib/active_model_serializers/adapter/json_api/deserialization.rb +213 -0
  85. data/lib/active_model_serializers/adapter/json_api/error.rb +96 -0
  86. data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +49 -0
  87. data/lib/active_model_serializers/adapter/json_api/link.rb +83 -0
  88. data/lib/active_model_serializers/adapter/json_api/meta.rb +37 -0
  89. data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +62 -0
  90. data/lib/active_model_serializers/adapter/json_api/relationship.rb +52 -0
  91. data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +37 -0
  92. data/lib/active_model_serializers/adapter/json_api.rb +516 -0
  93. data/lib/active_model_serializers/adapter/null.rb +9 -0
  94. data/lib/active_model_serializers/adapter.rb +92 -0
  95. data/lib/active_model_serializers/callbacks.rb +55 -0
  96. data/lib/active_model_serializers/deprecate.rb +55 -0
  97. data/lib/active_model_serializers/deserialization.rb +13 -0
  98. data/lib/active_model_serializers/json_pointer.rb +14 -0
  99. data/lib/active_model_serializers/key_transform.rb +70 -0
  100. data/lib/active_model_serializers/logging.rb +122 -0
  101. data/lib/active_model_serializers/model.rb +49 -0
  102. data/lib/active_model_serializers/railtie.rb +46 -0
  103. data/lib/active_model_serializers/register_jsonapi_renderer.rb +65 -0
  104. data/lib/active_model_serializers/serializable_resource.rb +81 -0
  105. data/lib/active_model_serializers/serialization_context.rb +32 -0
  106. data/lib/active_model_serializers/test/schema.rb +138 -0
  107. data/lib/active_model_serializers/test/serializer.rb +125 -0
  108. data/lib/active_model_serializers/test.rb +7 -0
  109. data/lib/active_model_serializers.rb +32 -89
  110. data/lib/generators/rails/USAGE +6 -0
  111. data/lib/generators/rails/resource_override.rb +10 -0
  112. data/lib/generators/rails/serializer_generator.rb +36 -0
  113. data/lib/generators/rails/templates/serializer.rb.erb +8 -0
  114. data/lib/grape/active_model_serializers.rb +14 -0
  115. data/lib/grape/formatters/active_model_serializers.rb +15 -0
  116. data/lib/grape/helpers/active_model_serializers.rb +16 -0
  117. data/test/action_controller/adapter_selector_test.rb +53 -0
  118. data/test/action_controller/explicit_serializer_test.rb +134 -0
  119. data/test/action_controller/json/include_test.rb +167 -0
  120. data/test/action_controller/json_api/deserialization_test.rb +112 -0
  121. data/test/action_controller/json_api/errors_test.rb +41 -0
  122. data/test/action_controller/json_api/linked_test.rb +197 -0
  123. data/test/action_controller/json_api/pagination_test.rb +116 -0
  124. data/test/action_controller/json_api/transform_test.rb +181 -0
  125. data/test/action_controller/serialization_scope_name_test.rb +229 -0
  126. data/test/action_controller/serialization_test.rb +469 -0
  127. data/test/active_model_serializers/adapter_for_test.rb +208 -0
  128. data/test/active_model_serializers/json_pointer_test.rb +20 -0
  129. data/test/active_model_serializers/key_transform_test.rb +263 -0
  130. data/test/active_model_serializers/logging_test.rb +77 -0
  131. data/test/active_model_serializers/model_test.rb +9 -0
  132. data/test/active_model_serializers/railtie_test_isolated.rb +63 -0
  133. data/test/active_model_serializers/serialization_context_test_isolated.rb +58 -0
  134. data/test/active_model_serializers/test/schema_test.rb +130 -0
  135. data/test/active_model_serializers/test/serializer_test.rb +62 -0
  136. data/test/active_record_test.rb +9 -0
  137. data/test/adapter/deprecation_test.rb +100 -0
  138. data/test/adapter/json/belongs_to_test.rb +45 -0
  139. data/test/adapter/json/collection_test.rb +90 -0
  140. data/test/adapter/json/has_many_test.rb +45 -0
  141. data/test/adapter/json/transform_test.rb +93 -0
  142. data/test/adapter/json_api/belongs_to_test.rb +155 -0
  143. data/test/adapter/json_api/collection_test.rb +95 -0
  144. data/test/adapter/json_api/errors_test.rb +78 -0
  145. data/test/adapter/json_api/fields_test.rb +87 -0
  146. data/test/adapter/json_api/has_many_embed_ids_test.rb +43 -0
  147. data/test/adapter/json_api/has_many_explicit_serializer_test.rb +96 -0
  148. data/test/adapter/json_api/has_many_test.rb +144 -0
  149. data/test/adapter/json_api/has_one_test.rb +80 -0
  150. data/test/adapter/json_api/json_api_test.rb +35 -0
  151. data/test/adapter/json_api/linked_test.rb +392 -0
  152. data/test/adapter/json_api/links_test.rb +93 -0
  153. data/test/adapter/json_api/pagination_links_test.rb +166 -0
  154. data/test/adapter/json_api/parse_test.rb +137 -0
  155. data/test/adapter/json_api/relationship_test.rb +161 -0
  156. data/test/adapter/json_api/relationships_test.rb +199 -0
  157. data/test/adapter/json_api/resource_identifier_test.rb +85 -0
  158. data/test/adapter/json_api/resource_meta_test.rb +100 -0
  159. data/test/adapter/json_api/toplevel_jsonapi_test.rb +82 -0
  160. data/test/adapter/json_api/transform_test.rb +502 -0
  161. data/test/adapter/json_api/type_test.rb +61 -0
  162. data/test/adapter/json_test.rb +45 -0
  163. data/test/adapter/null_test.rb +23 -0
  164. data/test/adapter/polymorphic_test.rb +171 -0
  165. data/test/adapter_test.rb +67 -0
  166. data/test/array_serializer_test.rb +20 -73
  167. data/test/benchmark/app.rb +65 -0
  168. data/test/benchmark/benchmarking_support.rb +67 -0
  169. data/test/benchmark/bm_caching.rb +119 -0
  170. data/test/benchmark/bm_transform.rb +34 -0
  171. data/test/benchmark/config.ru +3 -0
  172. data/test/benchmark/controllers.rb +84 -0
  173. data/test/benchmark/fixtures.rb +219 -0
  174. data/test/cache_test.rb +485 -0
  175. data/test/collection_serializer_test.rb +110 -0
  176. data/test/fixtures/active_record.rb +78 -0
  177. data/test/fixtures/poro.rb +282 -0
  178. data/test/generators/scaffold_controller_generator_test.rb +24 -0
  179. data/test/generators/serializer_generator_test.rb +57 -0
  180. data/test/grape_test.rb +82 -0
  181. data/test/include_tree/from_include_args_test.rb +26 -0
  182. data/test/include_tree/from_string_test.rb +94 -0
  183. data/test/include_tree/include_args_to_hash_test.rb +64 -0
  184. data/test/lint_test.rb +49 -0
  185. data/test/logger_test.rb +18 -0
  186. data/test/poro_test.rb +9 -0
  187. data/test/serializable_resource_test.rb +83 -0
  188. data/test/serializers/association_macros_test.rb +36 -0
  189. data/test/serializers/associations_test.rb +295 -0
  190. data/test/serializers/attribute_test.rb +151 -0
  191. data/test/serializers/attributes_test.rb +52 -0
  192. data/test/serializers/caching_configuration_test_isolated.rb +170 -0
  193. data/test/serializers/configuration_test.rb +32 -0
  194. data/test/serializers/fieldset_test.rb +14 -0
  195. data/test/serializers/meta_test.rb +196 -0
  196. data/test/serializers/options_test.rb +21 -0
  197. data/test/serializers/read_attribute_for_serialization_test.rb +79 -0
  198. data/test/serializers/root_test.rb +21 -0
  199. data/test/serializers/serialization_test.rb +55 -0
  200. data/test/serializers/serializer_for_test.rb +134 -0
  201. data/test/support/custom_schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
  202. data/test/support/isolated_unit.rb +79 -0
  203. data/test/support/rails5_shims.rb +47 -0
  204. data/test/support/rails_app.rb +45 -0
  205. data/test/support/schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
  206. data/test/support/schemas/active_model_serializers/test/schema_test/my/show.json +6 -0
  207. data/test/support/schemas/custom/show.json +7 -0
  208. data/test/support/schemas/hyper_schema.json +93 -0
  209. data/test/support/schemas/render_using_json_api.json +43 -0
  210. data/test/support/schemas/simple_json_pointers.json +10 -0
  211. data/test/support/serialization_testing.rb +53 -0
  212. data/test/test_helper.rb +48 -23
  213. metadata +449 -43
  214. data/DESIGN.textile +0 -586
  215. data/Gemfile.edge +0 -9
  216. data/bench/perf.rb +0 -43
  217. data/cruft.md +0 -19
  218. data/lib/active_model/array_serializer.rb +0 -104
  219. data/lib/active_record/serializer_override.rb +0 -16
  220. data/lib/generators/resource_override.rb +0 -13
  221. data/lib/generators/serializer/USAGE +0 -9
  222. data/lib/generators/serializer/serializer_generator.rb +0 -42
  223. data/lib/generators/serializer/templates/serializer.rb +0 -19
  224. data/test/association_test.rb +0 -592
  225. data/test/caching_test.rb +0 -96
  226. data/test/generators_test.rb +0 -85
  227. data/test/no_serialization_scope_test.rb +0 -34
  228. data/test/serialization_scope_name_test.rb +0 -67
  229. data/test/serialization_test.rb +0 -392
  230. data/test/serializer_support_test.rb +0 -51
  231. data/test/serializer_test.rb +0 -1465
  232. data/test/test_fakes.rb +0 -217
@@ -0,0 +1,84 @@
1
+ class PostController < ActionController::Base
2
+ POST =
3
+ begin
4
+ updated_at = Time.current
5
+ if ENV['BENCH_STRESS']
6
+ comments = (0..50).map do |i|
7
+ Comment.new(id: i, body: 'ZOMG A COMMENT', updated_at: updated_at + i)
8
+ end
9
+ else
10
+ comments = [Comment.new(id: 1, body: 'ZOMG A COMMENT', updated_at: updated_at)]
11
+ end
12
+ author = Author.new(id: 42, first_name: 'Joao', last_name: 'Moura')
13
+ Post.new(id: 1337, title: 'New Post', blog: nil, body: 'Body', comments: comments, author: author)
14
+ end
15
+
16
+ def render_with_caching_serializer
17
+ toggle_cache_status
18
+ render json: POST, serializer: CachingPostSerializer, adapter: :json, meta: { caching: perform_caching }
19
+ end
20
+
21
+ def render_with_fragment_caching_serializer
22
+ toggle_cache_status
23
+ render json: POST, serializer: FragmentCachingPostSerializer, adapter: :json, meta: { caching: perform_caching }
24
+ end
25
+
26
+ def render_with_non_caching_serializer
27
+ toggle_cache_status
28
+ render json: POST, adapter: :json, meta: { caching: perform_caching }
29
+ end
30
+
31
+ def render_cache_status
32
+ toggle_cache_status
33
+ # Uncomment to debug
34
+ # STDERR.puts cache_store.class
35
+ # STDERR.puts cache_dependencies
36
+ # ActiveSupport::Cache::Store.logger.debug [ActiveModelSerializers.config.cache_store, ActiveModelSerializers.config.perform_caching, CachingPostSerializer._cache, perform_caching, params].inspect
37
+ render json: { caching: perform_caching, meta: { cache_log: cache_messages, cache_status: cache_status } }.to_json
38
+ end
39
+
40
+ def clear
41
+ ActionController::Base.cache_store.clear
42
+ # Test caching is on
43
+ # Uncomment to turn on logger; possible performance issue
44
+ # logger = BenchmarkLogger.new
45
+ # ActiveSupport::Cache::Store.logger = logger # seems to be the best way
46
+ #
47
+ # the below is used in some rails tests but isn't available/working in all versions, so far as I can tell
48
+ # https://github.com/rails/rails/pull/15943
49
+ # ActiveSupport::Notifications.subscribe(/^cache_(.*)\.active_support$/) do |*args|
50
+ # logger.debug ActiveSupport::Notifications::Event.new(*args)
51
+ # end
52
+ render json: 'ok'.to_json
53
+ end
54
+
55
+ private
56
+
57
+ def cache_status
58
+ {
59
+ controller: perform_caching,
60
+ app: Rails.configuration.action_controller.perform_caching,
61
+ serializers: Rails.configuration.serializers.each_with_object({}) { |serializer, data| data[serializer.name] = serializer._cache.present? }
62
+ }
63
+ end
64
+
65
+ def cache_messages
66
+ ActiveSupport::Cache::Store.logger.is_a?(BenchmarkLogger) && ActiveSupport::Cache::Store.logger.messages.split("\n")
67
+ end
68
+
69
+ def toggle_cache_status
70
+ case params[:on]
71
+ when 'on'.freeze then self.perform_caching = true
72
+ when 'off'.freeze then self.perform_caching = false
73
+ else nil # no-op
74
+ end
75
+ end
76
+ end
77
+
78
+ Rails.application.routes.draw do
79
+ get '/status(/:on)' => 'post#render_cache_status'
80
+ get '/clear' => 'post#clear'
81
+ get '/caching(/:on)' => 'post#render_with_caching_serializer'
82
+ get '/fragment_caching(/:on)' => 'post#render_with_fragment_caching_serializer'
83
+ get '/non_caching(/:on)' => 'post#render_with_non_caching_serializer'
84
+ end
@@ -0,0 +1,219 @@
1
+ Rails.configuration.serializers = []
2
+ class AuthorSerializer < ActiveModel::Serializer
3
+ attributes :id, :first_name, :last_name
4
+
5
+ has_many :posts, embed: :ids
6
+ has_one :bio
7
+ end
8
+ Rails.configuration.serializers << AuthorSerializer
9
+
10
+ class BlogSerializer < ActiveModel::Serializer
11
+ attributes :id, :name
12
+ end
13
+ Rails.configuration.serializers << BlogSerializer
14
+
15
+ class CommentSerializer < ActiveModel::Serializer
16
+ attributes :id, :body, :updated_at
17
+
18
+ belongs_to :post
19
+ belongs_to :author
20
+ end
21
+ Rails.configuration.serializers << CommentSerializer
22
+
23
+ class PostSerializer < ActiveModel::Serializer
24
+ attributes :id, :title, :body
25
+
26
+ has_many :comments, serializer: CommentSerializer
27
+ belongs_to :blog, serializer: BlogSerializer
28
+ belongs_to :author, serializer: AuthorSerializer
29
+
30
+ link(:post_authors) { 'https://example.com/post_authors' }
31
+
32
+ meta do
33
+ {
34
+ rating: 5,
35
+ favorite_count: 10
36
+ }
37
+ end
38
+
39
+ def blog
40
+ Blog.new(id: 999, name: 'Custom blog')
41
+ end
42
+ end
43
+ Rails.configuration.serializers << PostSerializer
44
+
45
+ class CachingAuthorSerializer < AuthorSerializer
46
+ cache key: 'writer', skip_digest: true
47
+ end
48
+ Rails.configuration.serializers << CachingAuthorSerializer
49
+
50
+ class CachingCommentSerializer < CommentSerializer
51
+ cache expires_in: 1.day, skip_digest: true
52
+ end
53
+ Rails.configuration.serializers << CachingCommentSerializer
54
+
55
+ # see https://github.com/rails-api/active_model_serializers/pull/1690/commits/68715b8f99bc29677e8a47bb3f305f23c077024b#r60344532
56
+ class CachingPostSerializer < ActiveModel::Serializer
57
+ cache key: 'post', expires_in: 0.1, skip_digest: true
58
+
59
+ attributes :id, :title, :body
60
+
61
+ belongs_to :blog, serializer: BlogSerializer
62
+ belongs_to :author, serializer: CachingAuthorSerializer
63
+ has_many :comments, serializer: CachingCommentSerializer
64
+
65
+ link(:post_authors) { 'https://example.com/post_authors' }
66
+
67
+ meta do
68
+ {
69
+ rating: 5,
70
+ favorite_count: 10
71
+ }
72
+ end
73
+
74
+ def blog
75
+ Blog.new(id: 999, name: 'Custom blog')
76
+ end
77
+ end
78
+ Rails.configuration.serializers << CachingPostSerializer
79
+
80
+ class FragmentCachingAuthorSerializer < AuthorSerializer
81
+ cache key: 'writer', only: [:first_name, :last_name], skip_digest: true
82
+ end
83
+ Rails.configuration.serializers << FragmentCachingAuthorSerializer
84
+
85
+ class FragmentCachingCommentSerializer < CommentSerializer
86
+ cache expires_in: 1.day, except: [:updated_at], skip_digest: true
87
+ end
88
+ Rails.configuration.serializers << CachingCommentSerializer
89
+
90
+ # see https://github.com/rails-api/active_model_serializers/pull/1690/commits/68715b8f99bc29677e8a47bb3f305f23c077024b#r60344532
91
+ class FragmentCachingPostSerializer < ActiveModel::Serializer
92
+ cache key: 'post', expires_in: 0.1, skip_digest: true
93
+
94
+ attributes :id, :title, :body
95
+
96
+ belongs_to :blog, serializer: BlogSerializer
97
+ belongs_to :author, serializer: FragmentCachingAuthorSerializer
98
+ has_many :comments, serializer: FragmentCachingCommentSerializer
99
+
100
+ link(:post_authors) { 'https://example.com/post_authors' }
101
+
102
+ meta do
103
+ {
104
+ rating: 5,
105
+ favorite_count: 10
106
+ }
107
+ end
108
+
109
+ def blog
110
+ Blog.new(id: 999, name: 'Custom blog')
111
+ end
112
+ end
113
+ Rails.configuration.serializers << FragmentCachingPostSerializer
114
+
115
+ if ENV['ENABLE_ACTIVE_RECORD'] == 'true'
116
+ require 'active_record'
117
+
118
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
119
+ ActiveRecord::Schema.define do
120
+ self.verbose = false
121
+
122
+ create_table :blogs, force: true do |t|
123
+ t.string :name
124
+ t.timestamps null: false
125
+ end
126
+ create_table :authors, force: true do |t|
127
+ t.string :first_name
128
+ t.string :last_name
129
+ t.timestamps null: false
130
+ end
131
+ create_table :posts, force: true do |t|
132
+ t.string :title
133
+ t.text :body
134
+ t.references :author
135
+ t.references :blog
136
+ t.timestamps null: false
137
+ end
138
+ create_table :comments, force: true do |t|
139
+ t.text :body
140
+ t.references :author
141
+ t.references :post
142
+ t.timestamps null: false
143
+ end
144
+ end
145
+
146
+ class Comment < ActiveRecord::Base
147
+ belongs_to :author
148
+ belongs_to :post
149
+ end
150
+
151
+ class Author < ActiveRecord::Base
152
+ has_many :posts
153
+ has_many :comments
154
+ end
155
+
156
+ class Post < ActiveRecord::Base
157
+ has_many :comments
158
+ belongs_to :author
159
+ belongs_to :blog
160
+ end
161
+
162
+ class Blog < ActiveRecord::Base
163
+ has_many :posts
164
+ end
165
+ else
166
+ # ActiveModelSerializers::Model is a convenient
167
+ # serializable class to inherit from when making
168
+ # serializable non-activerecord objects.
169
+ class BenchmarkModel
170
+ include ActiveModel::Model
171
+ include ActiveModel::Serializers::JSON
172
+
173
+ attr_reader :attributes
174
+
175
+ def initialize(attributes = {})
176
+ @attributes = attributes
177
+ super
178
+ end
179
+
180
+ # Defaults to the downcased model name.
181
+ def id
182
+ attributes.fetch(:id) { self.class.name.downcase }
183
+ end
184
+
185
+ # Defaults to the downcased model name and updated_at
186
+ def cache_key
187
+ attributes.fetch(:cache_key) { "#{self.class.name.downcase}/#{id}" }
188
+ end
189
+
190
+ # Defaults to the time the serializer file was modified.
191
+ def updated_at
192
+ @updated_at ||= attributes.fetch(:updated_at) { File.mtime(__FILE__) }
193
+ end
194
+
195
+ def read_attribute_for_serialization(key)
196
+ if key == :id || key == 'id'
197
+ attributes.fetch(key) { id }
198
+ else
199
+ attributes[key]
200
+ end
201
+ end
202
+ end
203
+
204
+ class Comment < BenchmarkModel
205
+ attr_accessor :id, :body, :updated_at
206
+ end
207
+
208
+ class Author < BenchmarkModel
209
+ attr_accessor :id, :first_name, :last_name, :posts
210
+ end
211
+
212
+ class Post < BenchmarkModel
213
+ attr_accessor :id, :title, :body, :comments, :blog, :author
214
+ end
215
+
216
+ class Blog < BenchmarkModel
217
+ attr_accessor :id, :name
218
+ end
219
+ end