active_model_serializers 0.10.2 → 0.10.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +8 -1
  3. data/CHANGELOG.md +45 -3
  4. data/CODE_OF_CONDUCT.md +74 -0
  5. data/Gemfile +4 -1
  6. data/README.md +5 -2
  7. data/active_model_serializers.gemspec +2 -2
  8. data/docs/ARCHITECTURE.md +6 -7
  9. data/docs/README.md +2 -0
  10. data/docs/general/caching.md +7 -1
  11. data/docs/general/configuration_options.md +64 -0
  12. data/docs/general/rendering.md +35 -1
  13. data/docs/general/serializers.md +35 -5
  14. data/docs/howto/add_pagination_links.md +2 -2
  15. data/docs/howto/add_relationship_links.md +137 -0
  16. data/docs/howto/add_root_key.md +4 -0
  17. data/docs/howto/grape_integration.md +42 -0
  18. data/docs/howto/outside_controller_use.md +9 -2
  19. data/docs/howto/passing_arbitrary_options.md +2 -2
  20. data/docs/howto/test.md +2 -0
  21. data/docs/howto/upgrade_from_0_8_to_0_10.md +265 -0
  22. data/docs/integrations/ember-and-json-api.md +41 -24
  23. data/lib/action_controller/serialization.rb +9 -0
  24. data/lib/active_model/serializer.rb +19 -22
  25. data/lib/active_model/serializer/association.rb +19 -4
  26. data/lib/active_model/serializer/collection_serializer.rb +8 -5
  27. data/lib/active_model/serializer/{associations.rb → concerns/associations.rb} +8 -5
  28. data/lib/active_model/serializer/{attributes.rb → concerns/attributes.rb} +0 -0
  29. data/lib/active_model/serializer/{caching.rb → concerns/caching.rb} +5 -1
  30. data/lib/active_model/serializer/{configuration.rb → concerns/configuration.rb} +24 -1
  31. data/lib/active_model/serializer/{links.rb → concerns/links.rb} +0 -0
  32. data/lib/active_model/serializer/{meta.rb → concerns/meta.rb} +0 -0
  33. data/lib/active_model/serializer/{type.rb → concerns/type.rb} +0 -0
  34. data/lib/active_model/serializer/reflection.rb +37 -21
  35. data/lib/active_model/serializer/version.rb +1 -1
  36. data/lib/active_model_serializers.rb +1 -0
  37. data/lib/active_model_serializers/adapter/attributes.rb +3 -1
  38. data/lib/active_model_serializers/adapter/json_api.rb +15 -22
  39. data/lib/active_model_serializers/adapter/json_api/relationship.rb +30 -19
  40. data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +23 -9
  41. data/lib/active_model_serializers/key_transform.rb +4 -0
  42. data/lib/active_model_serializers/lookup_chain.rb +80 -0
  43. data/lib/active_model_serializers/model.rb +1 -1
  44. data/lib/active_model_serializers/serializable_resource.rb +6 -5
  45. data/lib/generators/rails/serializer_generator.rb +1 -1
  46. data/test/action_controller/json_api/fields_test.rb +57 -0
  47. data/test/action_controller/json_api/transform_test.rb +3 -3
  48. data/test/action_controller/lookup_proc_test.rb +49 -0
  49. data/test/action_controller/namespace_lookup_test.rb +226 -0
  50. data/test/active_model_serializers/key_transform_test.rb +32 -0
  51. data/test/active_model_serializers/model_test.rb +11 -0
  52. data/test/adapter/attributes_test.rb +43 -0
  53. data/test/adapter/json/transform_test.rb +1 -1
  54. data/test/adapter/json_api/fields_test.rb +4 -3
  55. data/test/adapter/json_api/has_many_test.rb +21 -0
  56. data/test/adapter/json_api/include_data_if_sideloaded_test.rb +166 -0
  57. data/test/adapter/json_api/linked_test.rb +24 -6
  58. data/test/adapter/json_api/links_test.rb +1 -1
  59. data/test/adapter/json_api/pagination_links_test.rb +17 -2
  60. data/test/adapter/json_api/relationship_test.rb +309 -73
  61. data/test/adapter/json_api/resource_identifier_test.rb +20 -0
  62. data/test/adapter/json_api/transform_test.rb +4 -3
  63. data/test/benchmark/benchmarking_support.rb +1 -1
  64. data/test/benchmark/bm_active_record.rb +81 -0
  65. data/test/benchmark/bm_adapter.rb +38 -0
  66. data/test/benchmark/bm_caching.rb +1 -1
  67. data/test/benchmark/bm_lookup_chain.rb +83 -0
  68. data/test/cache_test.rb +42 -4
  69. data/test/collection_serializer_test.rb +1 -1
  70. data/test/fixtures/poro.rb +44 -41
  71. data/test/generators/serializer_generator_test.rb +22 -5
  72. data/test/serializers/association_macros_test.rb +3 -2
  73. data/test/serializers/associations_test.rb +97 -22
  74. data/test/serializers/attribute_test.rb +1 -1
  75. data/test/serializers/serializer_for_test.rb +3 -3
  76. data/test/serializers/serializer_for_with_namespace_test.rb +87 -0
  77. data/test/support/serialization_testing.rb +16 -0
  78. data/test/test_helper.rb +1 -0
  79. metadata +35 -14
  80. data/test/adapter/json_api/relationships_test.rb +0 -204
@@ -39,6 +39,26 @@ module ActiveModelSerializers
39
39
  test_type_inflection(AuthorSerializer, 'authors', :plural)
40
40
  end
41
41
 
42
+ def test_type_with_namespace
43
+ Object.const_set(:Admin, Module.new)
44
+ model = Class.new(::Model)
45
+ Admin.const_set(:PowerUser, model)
46
+ serializer = Class.new(ActiveModel::Serializer)
47
+ Admin.const_set(:PowerUserSerializer, serializer)
48
+ with_namespace_separator '--' do
49
+ admin_user = Admin::PowerUser.new
50
+ serializer = Admin::PowerUserSerializer.new(admin_user)
51
+ expected = {
52
+ id: admin_user.id,
53
+ type: 'admin--power-users'
54
+ }
55
+
56
+ identifier = ResourceIdentifier.new(serializer, {})
57
+ actual = identifier.as_json
58
+ assert_equal(expected, actual)
59
+ end
60
+ end
61
+
42
62
  def test_id_defined_on_object
43
63
  test_id(AuthorSerializer, @model.id.to_s)
44
64
  end
@@ -4,7 +4,10 @@ module ActiveModelSerializers
4
4
  module Adapter
5
5
  class JsonApi
6
6
  class KeyCaseTest < ActiveSupport::TestCase
7
- Post = Class.new(::Model)
7
+ class Post < ::Model; end
8
+ class Author < ::Model; end
9
+ class Comment < ::Model; end
10
+
8
11
  class PostSerializer < ActiveModel::Serializer
9
12
  type 'posts'
10
13
  attributes :title, :body, :publish_at
@@ -23,13 +26,11 @@ module ActiveModelSerializers
23
26
  end
24
27
  end
25
28
 
26
- Author = Class.new(::Model)
27
29
  class AuthorSerializer < ActiveModel::Serializer
28
30
  type 'authors'
29
31
  attributes :first_name, :last_name
30
32
  end
31
33
 
32
- Comment = Class.new(::Model)
33
34
  class CommentSerializer < ActiveModel::Serializer
34
35
  type 'comments'
35
36
  attributes :body
@@ -36,7 +36,7 @@ module Benchmark
36
36
  version: ::ActiveModel::Serializer::VERSION.to_s,
37
37
  rails_version: ::Rails.version.to_s,
38
38
  iterations_per_second: entry.ips,
39
- iterations_per_second_standard_deviation: entry.stddev_percentage,
39
+ iterations_per_second_standard_deviation: entry.error_percentage,
40
40
  total_allocated_objects_per_iteration: count_total_allocated_objects(&block)
41
41
  }.to_json
42
42
 
@@ -0,0 +1,81 @@
1
+ require_relative './benchmarking_support'
2
+ require_relative './app'
3
+
4
+ time = 10
5
+ disable_gc = true
6
+
7
+ # This is to disable any key transform effects that may impact performance
8
+ ActiveModelSerializers.config.key_transform = :unaltered
9
+
10
+ ###########################################
11
+ # Setup active record models
12
+ ##########################################
13
+ require 'active_record'
14
+ require 'sqlite3'
15
+
16
+ # For debugging SQL output
17
+ # ActiveRecord::Base.logger = Logger.new(STDERR)
18
+
19
+ # Change the following to reflect your database settings
20
+ ActiveRecord::Base.establish_connection(
21
+ adapter: 'sqlite3',
22
+ database: ':memory:'
23
+ )
24
+
25
+ # Don't show migration output when constructing fake db
26
+ ActiveRecord::Migration.verbose = false
27
+
28
+ ActiveRecord::Schema.define do
29
+ create_table :authors, force: true do |t|
30
+ t.string :name
31
+ end
32
+
33
+ create_table :posts, force: true do |t|
34
+ t.text :body
35
+ t.string :title
36
+ t.references :author
37
+ end
38
+
39
+ create_table :profiles, force: true do |t|
40
+ t.text :project_url
41
+ t.text :bio
42
+ t.date :birthday
43
+ t.references :author
44
+ end
45
+ end
46
+
47
+ class Author < ActiveRecord::Base
48
+ has_one :profile
49
+ has_many :posts
50
+ end
51
+
52
+ class Post < ActiveRecord::Base
53
+ belongs_to :author
54
+ end
55
+
56
+ class Profile < ActiveRecord::Base
57
+ belongs_to :author
58
+ end
59
+
60
+ # Build out the data to serialize
61
+ author = Author.create(name: 'Preston Sego')
62
+ Profile.create(project_url: 'https://github.com/NullVoxPopuli', author: author)
63
+ 50.times do
64
+ Post.create(
65
+ body: 'something about how password restrictions are evil, and less secure, and with the math to prove it.',
66
+ title: 'Your bank is does not know how to do security',
67
+ author: author
68
+ )
69
+ end
70
+
71
+ Benchmark.ams('AR: attributes', time: time, disable_gc: disable_gc) do
72
+ ActiveModelSerializers::SerializableResource.new(author, adapter: :attributes, include: 'profile,posts').serializable_hash
73
+ end
74
+
75
+ Benchmark.ams('AR: json', time: time, disable_gc: disable_gc) do
76
+ ActiveModelSerializers::SerializableResource.new(author, adapter: :json, include: 'profile,posts').serializable_hash
77
+ end
78
+
79
+ Benchmark.ams('AR: JSON API', time: time, disable_gc: disable_gc) do
80
+ ActiveModelSerializers::SerializableResource.new(author, adapter: :json_api, include: 'profile,posts').serializable_hash
81
+ end
@@ -0,0 +1,38 @@
1
+ require_relative './benchmarking_support'
2
+ require_relative './app'
3
+
4
+ time = 10
5
+ disable_gc = true
6
+ ActiveModelSerializers.config.key_transform = :unaltered
7
+ has_many_relationships = (0..60).map do |i|
8
+ HasManyRelationship.new(id: i, body: 'ZOMG A HAS MANY RELATIONSHIP')
9
+ end
10
+ has_one_relationship = HasOneRelationship.new(
11
+ id: 42,
12
+ first_name: 'Joao',
13
+ last_name: 'Moura'
14
+ )
15
+ primary_resource = PrimaryResource.new(
16
+ id: 1337,
17
+ title: 'New PrimaryResource',
18
+ virtual_attribute: nil,
19
+ body: 'Body',
20
+ has_many_relationships: has_many_relationships,
21
+ has_one_relationship: has_one_relationship
22
+ )
23
+ serializer = PrimaryResourceSerializer.new(primary_resource)
24
+
25
+ Benchmark.ams('attributes', time: time, disable_gc: disable_gc) do
26
+ attributes = ActiveModelSerializers::Adapter::Attributes.new(serializer)
27
+ attributes.as_json
28
+ end
29
+
30
+ Benchmark.ams('json_api', time: time, disable_gc: disable_gc) do
31
+ json_api = ActiveModelSerializers::Adapter::JsonApi.new(serializer)
32
+ json_api.as_json
33
+ end
34
+
35
+ Benchmark.ams('json', time: time, disable_gc: disable_gc) do
36
+ json = ActiveModelSerializers::Adapter::Json.new(serializer)
37
+ json.as_json
38
+ end
@@ -4,7 +4,7 @@ require_relative './app'
4
4
  # https://github.com/ruby-bench/ruby-bench-suite/blob/8ad567f7e43a044ae48c36833218423bb1e2bd9d/rails/benchmarks/actionpack_router.rb
5
5
  class ApiAssertion
6
6
  include Benchmark::ActiveModelSerializers::TestMethods
7
- BadRevisionError = Class.new(StandardError)
7
+ class BadRevisionError < StandardError; end
8
8
 
9
9
  def valid?
10
10
  caching = get_caching
@@ -0,0 +1,83 @@
1
+ require_relative './benchmarking_support'
2
+ require_relative './app'
3
+
4
+ time = 10
5
+ disable_gc = true
6
+ ActiveModelSerializers.config.key_transform = :unaltered
7
+
8
+ module AmsBench
9
+ module Api
10
+ module V1
11
+ class PrimaryResourceSerializer < ActiveModel::Serializer
12
+ attributes :title, :body
13
+
14
+ has_many :has_many_relationships
15
+ end
16
+
17
+ class HasManyRelationshipSerializer < ActiveModel::Serializer
18
+ attribute :body
19
+ end
20
+ end
21
+ end
22
+ class PrimaryResourceSerializer < ActiveModel::Serializer
23
+ attributes :title, :body
24
+
25
+ has_many :has_many_relationships
26
+
27
+ class HasManyRelationshipSerializer < ActiveModel::Serializer
28
+ attribute :body
29
+ end
30
+ end
31
+ end
32
+
33
+ resource = PrimaryResource.new(
34
+ id: 1,
35
+ title: 'title',
36
+ body: 'body',
37
+ has_many_relationships: [
38
+ HasManyRelationship.new(id: 1, body: 'body1'),
39
+ HasManyRelationship.new(id: 2, body: 'body1')
40
+ ]
41
+ )
42
+
43
+ serialization = lambda do
44
+ ActiveModelSerializers::SerializableResource.new(resource, serializer: AmsBench::PrimaryResourceSerializer).as_json
45
+ ActiveModelSerializers::SerializableResource.new(resource, namespace: AmsBench::Api::V1).as_json
46
+ ActiveModelSerializers::SerializableResource.new(resource).as_json
47
+ end
48
+
49
+ def clear_cache
50
+ AmsBench::PrimaryResourceSerializer.serializers_cache.clear
51
+ AmsBench::Api::V1::PrimaryResourceSerializer.serializers_cache.clear
52
+ ActiveModel::Serializer.serializers_cache.clear
53
+ end
54
+
55
+ configurable = lambda do
56
+ clear_cache
57
+ Benchmark.ams('Configurable Lookup Chain', time: time, disable_gc: disable_gc, &serialization)
58
+ end
59
+
60
+ old = lambda do
61
+ clear_cache
62
+ module ActiveModel
63
+ class Serializer
64
+ def self.serializer_lookup_chain_for(klass, namespace = nil)
65
+ chain = []
66
+
67
+ resource_class_name = klass.name.demodulize
68
+ resource_namespace = klass.name.deconstantize
69
+ serializer_class_name = "#{resource_class_name}Serializer"
70
+
71
+ chain.push("#{namespace}::#{serializer_class_name}") if namespace
72
+ chain.push("#{name}::#{serializer_class_name}") if self != ActiveModel::Serializer
73
+ chain.push("#{resource_namespace}::#{serializer_class_name}")
74
+ chain
75
+ end
76
+ end
77
+ end
78
+
79
+ Benchmark.ams('Old Lookup Chain (v0.10)', time: time, disable_gc: disable_gc, &serialization)
80
+ end
81
+
82
+ configurable.call
83
+ old.call
@@ -4,22 +4,46 @@ require 'tempfile'
4
4
 
5
5
  module ActiveModelSerializers
6
6
  class CacheTest < ActiveSupport::TestCase
7
- UncachedAuthor = Class.new(Author) do
7
+ # Instead of a primitive cache key (i.e. a string), this class
8
+ # returns a list of objects that require to be expanded themselves.
9
+ class AuthorWithExpandableCacheElements < Author
10
+ # For the test purposes it's important that #to_s for HasCacheKey differs
11
+ # between instances, hence not a Struct.
12
+ class HasCacheKey
13
+ attr_reader :cache_key
14
+ def initialize(cache_key)
15
+ @cache_key = cache_key
16
+ end
17
+
18
+ def to_s
19
+ "HasCacheKey##{object_id}"
20
+ end
21
+ end
22
+
23
+ def cache_key
24
+ [
25
+ HasCacheKey.new(name),
26
+ HasCacheKey.new(id)
27
+ ]
28
+ end
29
+ end
30
+
31
+ class UncachedAuthor < Author
8
32
  # To confirm cache_key is set using updated_at and cache_key option passed to cache
9
33
  undef_method :cache_key
10
34
  end
11
35
 
12
- Article = Class.new(::Model) do
36
+ class Article < ::Model
13
37
  # To confirm error is raised when cache_key is not set and cache_key option not passed to cache
14
38
  undef_method :cache_key
15
39
  end
16
40
 
17
- ArticleSerializer = Class.new(ActiveModel::Serializer) do
41
+ class ArticleSerializer < ActiveModel::Serializer
18
42
  cache only: [:place], skip_digest: true
19
43
  attributes :title
20
44
  end
21
45
 
22
- InheritedRoleSerializer = Class.new(RoleSerializer) do
46
+ class InheritedRoleSerializer < RoleSerializer
23
47
  cache key: 'inherited_role', only: [:name, :special_attribute]
24
48
  attribute :special_attribute
25
49
  end
@@ -106,6 +130,20 @@ module ActiveModelSerializers
106
130
  assert_equal(uncached_author_serializer.attributes.to_json, cache_store.fetch(key).to_json)
107
131
  end
108
132
 
133
+ def test_cache_key_expansion
134
+ author = AuthorWithExpandableCacheElements.new(id: 10, name: 'hello')
135
+ same_author = AuthorWithExpandableCacheElements.new(id: 10, name: 'hello')
136
+ diff_author = AuthorWithExpandableCacheElements.new(id: 11, name: 'hello')
137
+
138
+ author_serializer = AuthorSerializer.new(author)
139
+ same_author_serializer = AuthorSerializer.new(same_author)
140
+ diff_author_serializer = AuthorSerializer.new(diff_author)
141
+ adapter = AuthorSerializer.serialization_adapter_instance
142
+
143
+ assert_equal(author_serializer.cache_key(adapter), same_author_serializer.cache_key(adapter))
144
+ refute_equal(author_serializer.cache_key(adapter), diff_author_serializer.cache_key(adapter))
145
+ end
146
+
109
147
  def test_default_cache_key_fallback
110
148
  render_object_with_cache(@comment)
111
149
  key = "#{@comment.cache_key}/#{adapter.cache_key}"
@@ -3,7 +3,7 @@ require 'test_helper'
3
3
  module ActiveModel
4
4
  class Serializer
5
5
  class CollectionSerializerTest < ActiveSupport::TestCase
6
- MessagesSerializer = Class.new(ActiveModel::Serializer) do
6
+ class MessagesSerializer < ActiveModel::Serializer
7
7
  type 'messages'
8
8
  end
9
9
 
@@ -50,18 +50,18 @@ class ProfilePreviewSerializer < ActiveModel::Serializer
50
50
  attributes :name
51
51
  end
52
52
 
53
- Post = Class.new(Model)
54
- Like = Class.new(Model)
55
- Author = Class.new(Model)
56
- Bio = Class.new(Model)
57
- Blog = Class.new(Model)
58
- Role = Class.new(Model)
59
- User = Class.new(Model)
60
- Location = Class.new(Model)
61
- Place = Class.new(Model)
62
- Tag = Class.new(Model)
63
- VirtualValue = Class.new(Model)
64
- Comment = Class.new(Model) do
53
+ class Post < Model; end
54
+ class Like < Model; end
55
+ class Author < Model; end
56
+ class Bio < Model; end
57
+ class Blog < Model; end
58
+ class Role < Model; end
59
+ class User < Model; end
60
+ class Location < Model; end
61
+ class Place < Model; end
62
+ class Tag < Model; end
63
+ class VirtualValue < Model; end
64
+ class Comment < Model
65
65
  # Uses a custom non-time-based cache key
66
66
  def cache_key
67
67
  "#{self.class.name.downcase}/#{id}"
@@ -87,10 +87,11 @@ class PolyTag < ActiveRecord::Base
87
87
  has_many :object_tags
88
88
  end
89
89
 
90
- module Spam; end
91
- Spam::UnrelatedLink = Class.new(Model)
90
+ module Spam
91
+ class UnrelatedLink < Model; end
92
+ end
92
93
 
93
- PostSerializer = Class.new(ActiveModel::Serializer) do
94
+ class PostSerializer < ActiveModel::Serializer
94
95
  cache key: 'post', expires_in: 0.1, skip_digest: true
95
96
  attributes :id, :title, :body
96
97
 
@@ -108,12 +109,12 @@ PostSerializer = Class.new(ActiveModel::Serializer) do
108
109
  end
109
110
  end
110
111
 
111
- SpammyPostSerializer = Class.new(ActiveModel::Serializer) do
112
+ class SpammyPostSerializer < ActiveModel::Serializer
112
113
  attributes :id
113
114
  has_many :related
114
115
  end
115
116
 
116
- CommentSerializer = Class.new(ActiveModel::Serializer) do
117
+ class CommentSerializer < ActiveModel::Serializer
117
118
  cache expires_in: 1.day, skip_digest: true
118
119
  attributes :id, :body
119
120
 
@@ -125,7 +126,7 @@ CommentSerializer = Class.new(ActiveModel::Serializer) do
125
126
  end
126
127
  end
127
128
 
128
- AuthorSerializer = Class.new(ActiveModel::Serializer) do
129
+ class AuthorSerializer < ActiveModel::Serializer
129
130
  cache key: 'writer', skip_digest: true
130
131
  attribute :id
131
132
  attribute :name
@@ -135,7 +136,7 @@ AuthorSerializer = Class.new(ActiveModel::Serializer) do
135
136
  has_one :bio
136
137
  end
137
138
 
138
- RoleSerializer = Class.new(ActiveModel::Serializer) do
139
+ class RoleSerializer < ActiveModel::Serializer
139
140
  cache only: [:name, :slug], skip_digest: true
140
141
  attributes :id, :name, :description
141
142
  attribute :friendly_id, key: :slug
@@ -147,13 +148,13 @@ RoleSerializer = Class.new(ActiveModel::Serializer) do
147
148
  belongs_to :author
148
149
  end
149
150
 
150
- LikeSerializer = Class.new(ActiveModel::Serializer) do
151
+ class LikeSerializer < ActiveModel::Serializer
151
152
  attributes :id, :time
152
153
 
153
154
  belongs_to :likeable
154
155
  end
155
156
 
156
- LocationSerializer = Class.new(ActiveModel::Serializer) do
157
+ class LocationSerializer < ActiveModel::Serializer
157
158
  cache only: [:address], skip_digest: true
158
159
  attributes :id, :lat, :lng
159
160
 
@@ -164,20 +165,20 @@ LocationSerializer = Class.new(ActiveModel::Serializer) do
164
165
  end
165
166
  end
166
167
 
167
- PlaceSerializer = Class.new(ActiveModel::Serializer) do
168
+ class PlaceSerializer < ActiveModel::Serializer
168
169
  attributes :id, :name
169
170
 
170
171
  has_many :locations
171
172
  end
172
173
 
173
- BioSerializer = Class.new(ActiveModel::Serializer) do
174
+ class BioSerializer < ActiveModel::Serializer
174
175
  cache except: [:content], skip_digest: true
175
176
  attributes :id, :content, :rating
176
177
 
177
178
  belongs_to :author
178
179
  end
179
180
 
180
- BlogSerializer = Class.new(ActiveModel::Serializer) do
181
+ class BlogSerializer < ActiveModel::Serializer
181
182
  cache key: 'blog'
182
183
  attributes :id, :name
183
184
 
@@ -185,50 +186,50 @@ BlogSerializer = Class.new(ActiveModel::Serializer) do
185
186
  has_many :articles
186
187
  end
187
188
 
188
- PaginatedSerializer = Class.new(ActiveModel::Serializer::CollectionSerializer) do
189
+ class PaginatedSerializer < ActiveModel::Serializer::CollectionSerializer
189
190
  def json_key
190
191
  'paginated'
191
192
  end
192
193
  end
193
194
 
194
- AlternateBlogSerializer = Class.new(ActiveModel::Serializer) do
195
+ class AlternateBlogSerializer < ActiveModel::Serializer
195
196
  attribute :id
196
197
  attribute :name, key: :title
197
198
  end
198
199
 
199
- CustomBlogSerializer = Class.new(ActiveModel::Serializer) do
200
+ class CustomBlogSerializer < ActiveModel::Serializer
200
201
  attribute :id
201
202
  attribute :special_attribute
202
203
 
203
204
  has_many :articles
204
205
  end
205
206
 
206
- CommentPreviewSerializer = Class.new(ActiveModel::Serializer) do
207
+ class CommentPreviewSerializer < ActiveModel::Serializer
207
208
  attributes :id
208
209
 
209
210
  belongs_to :post
210
211
  end
211
212
 
212
- AuthorPreviewSerializer = Class.new(ActiveModel::Serializer) do
213
+ class AuthorPreviewSerializer < ActiveModel::Serializer
213
214
  attributes :id
214
215
 
215
216
  has_many :posts
216
217
  end
217
218
 
218
- PostPreviewSerializer = Class.new(ActiveModel::Serializer) do
219
+ class PostPreviewSerializer < ActiveModel::Serializer
219
220
  attributes :title, :body, :id
220
221
 
221
222
  has_many :comments, serializer: CommentPreviewSerializer
222
223
  belongs_to :author, serializer: AuthorPreviewSerializer
223
224
  end
224
225
 
225
- PostWithTagsSerializer = Class.new(ActiveModel::Serializer) do
226
+ class PostWithTagsSerializer < ActiveModel::Serializer
226
227
  attributes :id
227
228
 
228
229
  has_many :tags
229
230
  end
230
231
 
231
- PostWithCustomKeysSerializer = Class.new(ActiveModel::Serializer) do
232
+ class PostWithCustomKeysSerializer < ActiveModel::Serializer
232
233
  attributes :id
233
234
 
234
235
  has_many :comments, key: :reviews
@@ -236,7 +237,7 @@ PostWithCustomKeysSerializer = Class.new(ActiveModel::Serializer) do
236
237
  has_one :blog, key: :site
237
238
  end
238
239
 
239
- VirtualValueSerializer = Class.new(ActiveModel::Serializer) do
240
+ class VirtualValueSerializer < ActiveModel::Serializer
240
241
  attributes :id
241
242
 
242
243
  has_many :reviews, virtual_value: [{ type: 'reviews', id: '1' },
@@ -250,34 +251,36 @@ VirtualValueSerializer = Class.new(ActiveModel::Serializer) do
250
251
  end
251
252
  end
252
253
 
253
- PolymorphicHasManySerializer = Class.new(ActiveModel::Serializer) do
254
+ class PolymorphicHasManySerializer < ActiveModel::Serializer
254
255
  attributes :id, :name
255
256
  end
256
257
 
257
- PolymorphicBelongsToSerializer = Class.new(ActiveModel::Serializer) do
258
+ class PolymorphicBelongsToSerializer < ActiveModel::Serializer
258
259
  attributes :id, :title
259
260
 
260
261
  has_one :imageable, serializer: PolymorphicHasManySerializer, polymorphic: true
261
262
  end
262
263
 
263
- PolymorphicSimpleSerializer = Class.new(ActiveModel::Serializer) do
264
+ class PolymorphicSimpleSerializer < ActiveModel::Serializer
264
265
  attributes :id
265
266
  end
266
267
 
267
- PolymorphicObjectTagSerializer = Class.new(ActiveModel::Serializer) do
268
+ class PolymorphicObjectTagSerializer < ActiveModel::Serializer
268
269
  attributes :id
269
270
 
270
271
  has_many :taggable, serializer: PolymorphicSimpleSerializer, polymorphic: true
271
272
  end
272
273
 
273
- PolymorphicTagSerializer = Class.new(ActiveModel::Serializer) do
274
+ class PolymorphicTagSerializer < ActiveModel::Serializer
274
275
  attributes :id, :phrase
275
276
 
276
277
  has_many :object_tags, serializer: PolymorphicObjectTagSerializer
277
278
  end
278
279
 
279
- Spam::UnrelatedLinkSerializer = Class.new(ActiveModel::Serializer) do
280
- cache only: [:id]
281
- attributes :id
280
+ module Spam
281
+ class UnrelatedLinkSerializer < ActiveModel::Serializer
282
+ cache only: [:id]
283
+ attributes :id
284
+ end
282
285
  end
283
286
  $VERBOSE = verbose