active_model_serializers 0.10.4 → 0.10.5

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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +7 -3
  3. data/CHANGELOG.md +25 -1
  4. data/README.md +4 -4
  5. data/active_model_serializers.gemspec +1 -1
  6. data/appveyor.yml +9 -3
  7. data/docs/general/logging.md +7 -0
  8. data/docs/general/serializers.md +3 -3
  9. data/docs/howto/add_pagination_links.md +13 -13
  10. data/docs/howto/add_relationship_links.md +24 -21
  11. data/docs/howto/outside_controller_use.md +3 -2
  12. data/docs/howto/serialize_poro.md +46 -5
  13. data/docs/howto/upgrade_from_0_8_to_0_10.md +1 -1
  14. data/lib/active_model/serializer/version.rb +1 -1
  15. data/lib/active_model_serializers.rb +8 -0
  16. data/lib/active_model_serializers/model.rb +108 -30
  17. data/lib/active_model_serializers/test/schema.rb +2 -2
  18. data/lib/generators/rails/resource_override.rb +1 -1
  19. data/test/action_controller/adapter_selector_test.rb +11 -2
  20. data/test/action_controller/json_api/fields_test.rb +15 -6
  21. data/test/action_controller/json_api/transform_test.rb +11 -3
  22. data/test/action_controller/namespace_lookup_test.rb +14 -8
  23. data/test/action_controller/serialization_scope_name_test.rb +12 -6
  24. data/test/action_controller/serialization_test.rb +1 -1
  25. data/test/active_model_serializers/model_test.rb +122 -2
  26. data/test/active_model_serializers/railtie_test_isolated.rb +12 -7
  27. data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +37 -19
  28. data/test/adapter/attributes_test.rb +2 -5
  29. data/test/adapter/json/has_many_test.rb +10 -2
  30. data/test/adapter/json_api/fields_test.rb +11 -3
  31. data/test/adapter/json_api/has_many_test.rb +10 -2
  32. data/test/adapter/json_api/include_data_if_sideloaded_test.rb +22 -5
  33. data/test/adapter/json_api/linked_test.rb +3 -3
  34. data/test/adapter/json_api/links_test.rb +1 -1
  35. data/test/adapter/json_api/relationship_test.rb +1 -1
  36. data/test/adapter/json_api/transform_test.rb +11 -3
  37. data/test/cache_test.rb +100 -28
  38. data/test/collection_serializer_test.rb +23 -10
  39. data/test/fixtures/active_record.rb +45 -10
  40. data/test/fixtures/poro.rb +115 -176
  41. data/test/generators/serializer_generator_test.rb +1 -0
  42. data/test/grape_test.rb +20 -2
  43. data/test/serializers/associations_test.rb +28 -7
  44. data/test/serializers/attribute_test.rb +4 -2
  45. data/test/serializers/caching_configuration_test_isolated.rb +6 -6
  46. data/test/serializers/options_test.rb +17 -6
  47. data/test/serializers/read_attribute_for_serialization_test.rb +3 -3
  48. data/test/serializers/serialization_test.rb +2 -2
  49. data/test/serializers/serializer_for_test.rb +6 -6
  50. data/test/serializers/serializer_for_with_namespace_test.rb +6 -5
  51. data/test/support/rails_app.rb +2 -0
  52. data/test/test_helper.rb +12 -0
  53. metadata +13 -7
@@ -4,11 +4,13 @@ require 'support/isolated_unit'
4
4
  class RailtieTest < ActiveSupport::TestCase
5
5
  include ActiveSupport::Testing::Isolation
6
6
 
7
- class WithRails < RailtieTest
7
+ class WithRailsRequiredFirst < RailtieTest
8
8
  setup do
9
9
  require 'rails'
10
10
  require 'active_model_serializers'
11
- make_basic_app
11
+ make_basic_app do |app|
12
+ app.config.action_controller.perform_caching = true
13
+ end
12
14
  end
13
15
 
14
16
  test 'mixes ActionController::Serialization into ActionController::Base' do
@@ -32,14 +34,17 @@ class RailtieTest < ActiveSupport::TestCase
32
34
 
33
35
  test 'it is configured for caching' do
34
36
  assert_equal ActionController::Base.cache_store, ActiveModelSerializers.config.cache_store
35
- assert_equal Rails.configuration.action_controller.perform_caching, ActiveModelSerializers.config.perform_caching
37
+ assert_equal true, Rails.configuration.action_controller.perform_caching
38
+ assert_equal true, ActiveModelSerializers.config.perform_caching
36
39
  end
37
40
  end
38
41
 
39
- class WithoutRails < RailtieTest
42
+ class WithoutRailsRequiredFirst < RailtieTest
40
43
  setup do
41
44
  require 'active_model_serializers'
42
- make_basic_app
45
+ make_basic_app do |app|
46
+ app.config.action_controller.perform_caching = true
47
+ end
43
48
  end
44
49
 
45
50
  test 'does not mix ActionController::Serialization into ActionController::Base' do
@@ -56,8 +61,8 @@ class RailtieTest < ActiveSupport::TestCase
56
61
  test 'it is not configured for caching' do
57
62
  refute_nil ActionController::Base.cache_store
58
63
  assert_nil ActiveModelSerializers.config.cache_store
59
- refute Rails.configuration.action_controller.perform_caching
60
- refute ActiveModelSerializers.config.perform_caching
64
+ assert_equal true, Rails.configuration.action_controller.perform_caching
65
+ assert_nil ActiveModelSerializers.config.perform_caching
61
66
  end
62
67
  end
63
68
  end
@@ -12,7 +12,17 @@ class JsonApiRendererTest < ActionDispatch::IntegrationTest
12
12
  end
13
13
 
14
14
  def render_with_jsonapi_renderer
15
- author = Author.new(params[:data][:attributes])
15
+ permitted_params = params.permit(data: [:id, :type, attributes: [:name]])
16
+ permitted_params = permitted_params.to_h.with_indifferent_access
17
+ attributes =
18
+ if permitted_params[:data]
19
+ permitted_params[:data][:attributes].merge(id: permitted_params[:data][:id])
20
+ else
21
+ # Rails returns empty params when no mime type can be negotiated.
22
+ # (Until https://github.com/rails/rails/pull/26632 is reviewed.)
23
+ permitted_params
24
+ end
25
+ author = Author.new(attributes)
16
26
  render jsonapi: author
17
27
  end
18
28
 
@@ -32,6 +42,17 @@ class JsonApiRendererTest < ActionDispatch::IntegrationTest
32
42
  assert_equal(expected, TestController.last_request_parameters)
33
43
  end
34
44
 
45
+ def define_author_model_and_serializer
46
+ TestController.const_set(:Author, Class.new(ActiveModelSerializers::Model) do
47
+ attributes :id, :name
48
+ end)
49
+ TestController.const_set(:AuthorSerializer, Class.new(ActiveModel::Serializer) do
50
+ type 'users'
51
+ attribute :id
52
+ attribute :name
53
+ end)
54
+ end
55
+
35
56
  class WithoutRenderer < JsonApiRendererTest
36
57
  setup do
37
58
  require 'rails'
@@ -47,6 +68,7 @@ class JsonApiRendererTest < ActionDispatch::IntegrationTest
47
68
  match ':action', to: TestController, via: [:get, :post]
48
69
  end
49
70
  end
71
+ define_author_model_and_serializer
50
72
  end
51
73
 
52
74
  def test_jsonapi_parser_not_registered
@@ -59,18 +81,12 @@ class JsonApiRendererTest < ActionDispatch::IntegrationTest
59
81
  end
60
82
 
61
83
  def test_jsonapi_renderer_not_registered
62
- expected = {
63
- 'data' => {
64
- 'attributes' => {
65
- 'name' => 'Johnny Rico'
66
- },
67
- 'type' => 'users'
68
- }
69
- }
70
- payload = '{"data": {"attributes": {"name": "Johnny Rico"}, "type": "authors"}}'
84
+ payload = '{"data": {"attributes": {"name": "Johnny Rico"}, "type": "users", "id": "36c9c04e-86b1-4636-a5b0-8616672d1765"}}'
71
85
  headers = { 'CONTENT_TYPE' => 'application/vnd.api+json' }
72
86
  post '/render_with_jsonapi_renderer', params: payload, headers: headers
73
- assert expected, response.body
87
+ assert_equal '', response.body
88
+ assert_equal 500, response.status
89
+ assert_equal ActionView::MissingTemplate, request.env['action_dispatch.exception'].class
74
90
  end
75
91
 
76
92
  def test_jsonapi_parser
@@ -98,6 +114,7 @@ class JsonApiRendererTest < ActionDispatch::IntegrationTest
98
114
  match ':action', to: TestController, via: [:get, :post]
99
115
  end
100
116
  end
117
+ define_author_model_and_serializer
101
118
  end
102
119
 
103
120
  def test_jsonapi_parser_registered
@@ -113,16 +130,16 @@ class JsonApiRendererTest < ActionDispatch::IntegrationTest
113
130
  def test_jsonapi_renderer_registered
114
131
  expected = {
115
132
  'data' => {
116
- 'attributes' => {
117
- 'name' => 'Johnny Rico'
118
- },
119
- 'type' => 'users'
133
+ 'id' => '36c9c04e-86b1-4636-a5b0-8616672d1765',
134
+ 'type' => 'users',
135
+ 'attributes' => { 'name' => 'Johnny Rico' }
120
136
  }
121
137
  }
122
- payload = '{"data": {"attributes": {"name": "Johnny Rico"}, "type": "authors"}}'
138
+
139
+ payload = '{"data": {"attributes": {"name": "Johnny Rico"}, "type": "users", "id": "36c9c04e-86b1-4636-a5b0-8616672d1765"}}'
123
140
  headers = { 'CONTENT_TYPE' => 'application/vnd.api+json' }
124
141
  post '/render_with_jsonapi_renderer', params: payload, headers: headers
125
- assert expected, response.body
142
+ assert_equal expected.to_json, response.body
126
143
  end
127
144
 
128
145
  def test_jsonapi_parser
@@ -132,10 +149,11 @@ class JsonApiRendererTest < ActionDispatch::IntegrationTest
132
149
  'attributes' => {
133
150
  'name' => 'John Doe'
134
151
  },
135
- 'type' => 'users'
152
+ 'type' => 'users',
153
+ 'id' => '36c9c04e-86b1-4636-a5b0-8616672d1765'
136
154
  }
137
155
  },
138
- '{"data": {"attributes": {"name": "John Doe"}, "type": "users"}}',
156
+ '{"data": {"attributes": {"name": "John Doe"}, "type": "users", "id": "36c9c04e-86b1-4636-a5b0-8616672d1765"}}',
139
157
  'CONTENT_TYPE' => 'application/vnd.api+json'
140
158
  )
141
159
  end
@@ -3,11 +3,8 @@ require 'test_helper'
3
3
  module ActiveModelSerializers
4
4
  module Adapter
5
5
  class AttributesTest < ActiveSupport::TestCase
6
- class Person
7
- include ActiveModel::Model
8
- include ActiveModel::Serialization
9
-
10
- attr_accessor :first_name, :last_name
6
+ class Person < ActiveModelSerializers::Model
7
+ attributes :first_name, :last_name
11
8
  end
12
9
 
13
10
  class PersonSerializer < ActiveModel::Serializer
@@ -4,6 +4,10 @@ module ActiveModelSerializers
4
4
  module Adapter
5
5
  class Json
6
6
  class HasManyTestTest < ActiveSupport::TestCase
7
+ class ModelWithoutSerializer < ::Model
8
+ attributes :id, :name
9
+ end
10
+
7
11
  def setup
8
12
  ActionController::Base.cache_store.clear
9
13
  @author = Author.new(id: 1, name: 'Steve K.')
@@ -16,7 +20,7 @@ module ActiveModelSerializers
16
20
  @second_comment.post = @post
17
21
  @blog = Blog.new(id: 1, name: 'My Blog!!')
18
22
  @post.blog = @blog
19
- @tag = Tag.new(id: 1, name: '#hash_tag')
23
+ @tag = ModelWithoutSerializer.new(id: 1, name: '#hash_tag')
20
24
  @post.tags = [@tag]
21
25
  end
22
26
 
@@ -30,7 +34,11 @@ module ActiveModelSerializers
30
34
  end
31
35
 
32
36
  def test_has_many_with_no_serializer
33
- serializer = PostWithTagsSerializer.new(@post)
37
+ post_serializer_class = Class.new(ActiveModel::Serializer) do
38
+ attributes :id
39
+ has_many :tags
40
+ end
41
+ serializer = post_serializer_class.new(@post)
34
42
  adapter = ActiveModelSerializers::Adapter::Json.new(serializer)
35
43
  assert_equal({
36
44
  id: 42,
@@ -4,9 +4,17 @@ module ActiveModelSerializers
4
4
  module Adapter
5
5
  class JsonApi
6
6
  class FieldsTest < ActiveSupport::TestCase
7
- class Post < ::Model; end
8
- class Author < ::Model; end
9
- class Comment < ::Model; end
7
+ class Post < ::Model
8
+ attributes :title, :body
9
+ associations :author, :comments
10
+ end
11
+ class Author < ::Model
12
+ attributes :name, :birthday
13
+ end
14
+ class Comment < ::Model
15
+ attributes :body
16
+ associations :author, :post
17
+ end
10
18
 
11
19
  class PostSerializer < ActiveModel::Serializer
12
20
  type 'posts'
@@ -4,6 +4,10 @@ module ActiveModelSerializers
4
4
  module Adapter
5
5
  class JsonApi
6
6
  class HasManyTest < ActiveSupport::TestCase
7
+ class ModelWithoutSerializer < ::Model
8
+ attributes :id, :name
9
+ end
10
+
7
11
  def setup
8
12
  ActionController::Base.cache_store.clear
9
13
  @author = Author.new(id: 1, name: 'Steve K.')
@@ -26,7 +30,7 @@ module ActiveModelSerializers
26
30
  @blog.articles = [@post]
27
31
  @post.blog = @blog
28
32
  @post_without_comments.blog = nil
29
- @tag = Tag.new(id: 1, name: '#hash_tag')
33
+ @tag = ModelWithoutSerializer.new(id: 1, name: '#hash_tag')
30
34
  @post.tags = [@tag]
31
35
  @serializer = PostSerializer.new(@post)
32
36
  @adapter = ActiveModelSerializers::Adapter::JsonApi.new(@serializer)
@@ -129,7 +133,11 @@ module ActiveModelSerializers
129
133
  end
130
134
 
131
135
  def test_has_many_with_no_serializer
132
- serializer = PostWithTagsSerializer.new(@post)
136
+ post_serializer_class = Class.new(ActiveModel::Serializer) do
137
+ attributes :id
138
+ has_many :tags
139
+ end
140
+ serializer = post_serializer_class.new(@post)
133
141
  adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer)
134
142
 
135
143
  assert_equal({
@@ -5,18 +5,30 @@ module ActiveModel
5
5
  module Adapter
6
6
  class JsonApi
7
7
  class IncludeParamTest < ActiveSupport::TestCase
8
- IncludeParamAuthor = Class.new(::Model)
8
+ IncludeParamAuthor = Class.new(::Model) do
9
+ associations :tags, :posts
10
+ end
9
11
 
10
12
  class CustomCommentLoader
11
13
  def all
12
14
  [{ foo: 'bar' }]
13
15
  end
14
16
  end
17
+ class Tag < ::Model
18
+ attributes :id, :name
19
+ end
15
20
 
16
21
  class TagSerializer < ActiveModel::Serializer
22
+ type 'tags'
17
23
  attributes :id, :name
18
24
  end
19
25
 
26
+ class PostWithTagsSerializer < ActiveModel::Serializer
27
+ type 'posts'
28
+ attributes :id
29
+ has_many :tags
30
+ end
31
+
20
32
  class IncludeParamAuthorSerializer < ActiveModel::Serializer
21
33
  class_attribute :comment_loader
22
34
 
@@ -144,20 +156,25 @@ module ActiveModel
144
156
  end
145
157
 
146
158
  def test_node_not_included_when_no_link
147
- expected = nil
148
- assert_relationship(:unlinked_tags, expected)
159
+ expected = { meta: {} }
160
+ assert_relationship(:unlinked_tags, expected, key_transform: :unaltered)
149
161
  end
150
162
 
151
163
  private
152
164
 
165
+ def assert_relationship(relationship_name, expected, opts = {})
166
+ actual = relationship_data(relationship_name, opts)
167
+ assert_equal(expected, actual)
168
+ end
169
+
153
170
  def result(opts)
154
171
  opts = { adapter: :json_api }.merge(opts)
155
172
  serializable(@author, opts).serializable_hash
156
173
  end
157
174
 
158
- def assert_relationship(relationship_name, expected, opts = {})
175
+ def relationship_data(relationship_name, opts = {})
159
176
  hash = result(opts)
160
- assert_equal(expected, hash[:data][:relationships][relationship_name])
177
+ hash[:data][:relationships][relationship_name]
161
178
  end
162
179
  end
163
180
  end
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class NestedPost < ::Model; end
3
+ class NestedPost < ::Model; associations :nested_posts end
4
4
  class NestedPostSerializer < ActiveModel::Serializer
5
5
  has_many :nested_posts
6
6
  end
@@ -301,8 +301,8 @@ module ActiveModelSerializers
301
301
  end
302
302
 
303
303
  class NoDuplicatesTest < ActiveSupport::TestCase
304
- class Post < ::Model; end
305
- class Author < ::Model; end
304
+ class Post < ::Model; associations :author end
305
+ class Author < ::Model; associations :posts, :roles, :bio end
306
306
 
307
307
  class PostSerializer < ActiveModel::Serializer
308
308
  type 'posts'
@@ -4,7 +4,7 @@ module ActiveModelSerializers
4
4
  module Adapter
5
5
  class JsonApi
6
6
  class LinksTest < ActiveSupport::TestCase
7
- class LinkAuthor < ::Model; end
7
+ class LinkAuthor < ::Model; associations :posts end
8
8
  class LinkAuthorSerializer < ActiveModel::Serializer
9
9
  link :self do
10
10
  href "http://example.com/link_author/#{object.id}"
@@ -384,7 +384,7 @@ module ActiveModelSerializers
384
384
 
385
385
  def new_model(model_attributes)
386
386
  Class.new(ActiveModelSerializers::Model) do
387
- attr_accessor(*model_attributes.keys)
387
+ attributes(*model_attributes.keys)
388
388
 
389
389
  def self.name
390
390
  'TestModel'
@@ -4,9 +4,17 @@ module ActiveModelSerializers
4
4
  module Adapter
5
5
  class JsonApi
6
6
  class KeyCaseTest < ActiveSupport::TestCase
7
- class Post < ::Model; end
8
- class Author < ::Model; end
9
- class Comment < ::Model; end
7
+ class Post < ::Model
8
+ attributes :title, :body, :publish_at
9
+ associations :author, :comments
10
+ end
11
+ class Author < ::Model
12
+ attributes :first_name, :last_name
13
+ end
14
+ class Comment < ::Model
15
+ attributes :body
16
+ associations :author, :post
17
+ end
10
18
 
11
19
  class PostSerializer < ActiveModel::Serializer
12
20
  type 'posts'
data/test/cache_test.rb CHANGED
@@ -4,6 +4,20 @@ require 'tempfile'
4
4
 
5
5
  module ActiveModelSerializers
6
6
  class CacheTest < ActiveSupport::TestCase
7
+ class Article < ::Model
8
+ attributes :title
9
+ # To confirm error is raised when cache_key is not set and cache_key option not passed to cache
10
+ undef_method :cache_key
11
+ end
12
+ class ArticleSerializer < ActiveModel::Serializer
13
+ cache only: [:place], skip_digest: true
14
+ attributes :title
15
+ end
16
+
17
+ class Author < ::Model
18
+ attributes :id, :name
19
+ associations :posts, :bio, :roles
20
+ end
7
21
  # Instead of a primitive cache key (i.e. a string), this class
8
22
  # returns a list of objects that require to be expanded themselves.
9
23
  class AuthorWithExpandableCacheElements < Author
@@ -27,22 +41,73 @@ module ActiveModelSerializers
27
41
  ]
28
42
  end
29
43
  end
30
-
31
44
  class UncachedAuthor < Author
32
45
  # To confirm cache_key is set using updated_at and cache_key option passed to cache
33
46
  undef_method :cache_key
34
47
  end
48
+ class AuthorSerializer < ActiveModel::Serializer
49
+ cache key: 'writer', skip_digest: true
50
+ attributes :id, :name
35
51
 
36
- class Article < ::Model
37
- # To confirm error is raised when cache_key is not set and cache_key option not passed to cache
38
- undef_method :cache_key
52
+ has_many :posts
53
+ has_many :roles
54
+ has_one :bio
39
55
  end
40
56
 
41
- class ArticleSerializer < ActiveModel::Serializer
42
- cache only: [:place], skip_digest: true
43
- attributes :title
57
+ class Blog < ::Model
58
+ attributes :name
59
+ associations :writer
44
60
  end
61
+ class BlogSerializer < ActiveModel::Serializer
62
+ cache key: 'blog'
63
+ attributes :id, :name
64
+
65
+ belongs_to :writer
66
+ end
67
+
68
+ class Comment < ::Model
69
+ attributes :id, :body
70
+ associations :post, :author
45
71
 
72
+ # Uses a custom non-time-based cache key
73
+ def cache_key
74
+ "comment/#{id}"
75
+ end
76
+ end
77
+ class CommentSerializer < ActiveModel::Serializer
78
+ cache expires_in: 1.day, skip_digest: true
79
+ attributes :id, :body
80
+ belongs_to :post
81
+ belongs_to :author
82
+ end
83
+
84
+ class Post < ::Model
85
+ attributes :id, :title, :body
86
+ associations :author, :comments, :blog
87
+ end
88
+ class PostSerializer < ActiveModel::Serializer
89
+ cache key: 'post', expires_in: 0.1, skip_digest: true
90
+ attributes :id, :title, :body
91
+
92
+ has_many :comments
93
+ belongs_to :blog
94
+ belongs_to :author
95
+ end
96
+
97
+ class Role < ::Model
98
+ attributes :name, :description, :special_attribute
99
+ associations :author
100
+ end
101
+ class RoleSerializer < ActiveModel::Serializer
102
+ cache only: [:name, :slug], skip_digest: true
103
+ attributes :id, :name, :description
104
+ attribute :friendly_id, key: :slug
105
+ belongs_to :author
106
+
107
+ def friendly_id
108
+ "#{object.name}-#{object.id}"
109
+ end
110
+ end
46
111
  class InheritedRoleSerializer < RoleSerializer
47
112
  cache key: 'inherited_role', only: [:name, :special_attribute]
48
113
  attribute :special_attribute
@@ -51,10 +116,10 @@ module ActiveModelSerializers
51
116
  setup do
52
117
  cache_store.clear
53
118
  @comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
54
- @post = Post.new(title: 'New Post', body: 'Body')
119
+ @post = Post.new(id: 'post', title: 'New Post', body: 'Body')
55
120
  @bio = Bio.new(id: 1, content: 'AMS Contributor')
56
- @author = Author.new(name: 'Joao M. D. Moura')
57
- @blog = Blog.new(id: 999, name: 'Custom blog', writer: @author, articles: [])
121
+ @author = Author.new(id: 'author', name: 'Joao M. D. Moura')
122
+ @blog = Blog.new(id: 999, name: 'Custom blog', writer: @author)
58
123
  @role = Role.new(name: 'Great Author')
59
124
  @location = Location.new(lat: '-23.550520', lng: '-46.633309')
60
125
  @place = Place.new(name: 'Amazing Place')
@@ -117,7 +182,7 @@ module ActiveModelSerializers
117
182
  def test_cache_key_definition
118
183
  assert_equal('post', @post_serializer.class._cache_key)
119
184
  assert_equal('writer', @author_serializer.class._cache_key)
120
- assert_equal(nil, @comment_serializer.class._cache_key)
185
+ assert_nil(@comment_serializer.class._cache_key)
121
186
  end
122
187
 
123
188
  def test_cache_key_interpolation_with_updated_at_when_cache_key_is_not_defined_on_object
@@ -160,7 +225,7 @@ module ActiveModelSerializers
160
225
 
161
226
  def test_cache_options_definition
162
227
  assert_equal({ expires_in: 0.1, skip_digest: true }, @post_serializer.class._cache_options)
163
- assert_equal(nil, @blog_serializer.class._cache_options)
228
+ assert_nil(@blog_serializer.class._cache_options)
164
229
  assert_equal({ expires_in: 1.day, skip_digest: true }, @comment_serializer.class._cache_options)
165
230
  end
166
231
 
@@ -171,8 +236,8 @@ module ActiveModelSerializers
171
236
 
172
237
  def test_associations_separately_cache
173
238
  cache_store.clear
174
- assert_equal(nil, cache_store.fetch(@post.cache_key))
175
- assert_equal(nil, cache_store.fetch(@comment.cache_key))
239
+ assert_nil(cache_store.fetch(@post.cache_key))
240
+ assert_nil(cache_store.fetch(@comment.cache_key))
176
241
 
177
242
  Timecop.freeze(Time.current) do
178
243
  render_object_with_cache(@post)
@@ -244,7 +309,7 @@ module ActiveModelSerializers
244
309
  # rubocop:disable Metrics/AbcSize
245
310
  def test_a_serializer_rendered_by_two_adapter_returns_differently_fetch_attributes
246
311
  Object.const_set(:Alert, Class.new(ActiveModelSerializers::Model) do
247
- attr_accessor :id, :status, :resource, :started_at, :ended_at, :updated_at, :created_at
312
+ attributes :id, :status, :resource, :started_at, :ended_at, :updated_at, :created_at
248
313
  end)
249
314
  Object.const_set(:UncachedAlertSerializer, Class.new(ActiveModel::Serializer) do
250
315
  attributes :id, :status, :resource, :started_at, :ended_at, :updated_at, :created_at
@@ -271,7 +336,7 @@ module ActiveModelSerializers
271
336
  ended_at: nil,
272
337
  updated_at: alert.updated_at,
273
338
  created_at: alert.created_at
274
- }
339
+ }.with_indifferent_access
275
340
  expected_cached_jsonapi_attributes = {
276
341
  id: '1',
277
342
  type: 'alerts',
@@ -283,15 +348,15 @@ module ActiveModelSerializers
283
348
  updated_at: alert.updated_at,
284
349
  created_at: alert.created_at
285
350
  }
286
- }
351
+ }.with_indifferent_access
287
352
 
288
353
  # Assert attributes are serialized correctly
289
354
  serializable_alert = serializable(alert, serializer: AlertSerializer, adapter: :attributes)
290
- attributes_serialization = serializable_alert.as_json
355
+ attributes_serialization = serializable_alert.as_json.with_indifferent_access
291
356
  assert_equal expected_fetch_attributes, alert.attributes
292
357
  assert_equal alert.attributes, attributes_serialization
293
358
  attributes_cache_key = serializable_alert.adapter.serializer.cache_key(serializable_alert.adapter)
294
- assert_equal attributes_serialization, cache_store.fetch(attributes_cache_key)
359
+ assert_equal attributes_serialization, cache_store.fetch(attributes_cache_key).with_indifferent_access
295
360
 
296
361
  serializable_alert = serializable(alert, serializer: AlertSerializer, adapter: :json_api)
297
362
  jsonapi_cache_key = serializable_alert.adapter.serializer.cache_key(serializable_alert.adapter)
@@ -303,7 +368,7 @@ module ActiveModelSerializers
303
368
  serializable_alert = serializable(alert, serializer: UncachedAlertSerializer, adapter: :json_api)
304
369
  assert_equal serializable_alert.as_json, jsonapi_serialization
305
370
 
306
- cached_serialization = cache_store.fetch(jsonapi_cache_key)
371
+ cached_serialization = cache_store.fetch(jsonapi_cache_key).with_indifferent_access
307
372
  assert_equal expected_cached_jsonapi_attributes, cached_serialization
308
373
  ensure
309
374
  Object.send(:remove_const, :Alert)
@@ -314,12 +379,14 @@ module ActiveModelSerializers
314
379
 
315
380
  def test_uses_file_digest_in_cache_key
316
381
  render_object_with_cache(@blog)
317
- key = "#{@blog.cache_key}/#{adapter.cache_key}/#{::Model::FILE_DIGEST}"
382
+ file_digest = Digest::MD5.hexdigest(File.open(__FILE__).read)
383
+ key = "#{@blog.cache_key}/#{adapter.cache_key}/#{file_digest}"
318
384
  assert_equal(@blog_serializer.attributes, cache_store.fetch(key))
319
385
  end
320
386
 
321
387
  def test_cache_digest_definition
322
- assert_equal(::Model::FILE_DIGEST, @post_serializer.class._cache_digest)
388
+ file_digest = Digest::MD5.hexdigest(File.open(__FILE__).read)
389
+ assert_equal(file_digest, @post_serializer.class._cache_digest)
323
390
  end
324
391
 
325
392
  def test_object_cache_keys
@@ -329,11 +396,15 @@ module ActiveModelSerializers
329
396
  actual = ActiveModel::Serializer.object_cache_keys(serializable.adapter.serializer, serializable.adapter, include_directive)
330
397
 
331
398
  assert_equal 3, actual.size
332
- assert actual.any? { |key| key == "comment/1/#{serializable.adapter.cache_key}" }
333
- assert actual.any? { |key| key =~ %r{post/post-\d+} }
334
- assert actual.any? { |key| key =~ %r{author/author-\d+} }
399
+ expected_key = "comment/1/#{serializable.adapter.cache_key}"
400
+ assert actual.any? { |key| key == expected_key }, "actual '#{actual}' should include #{expected_key}"
401
+ expected_key = %r{post/post-\d+}
402
+ assert actual.any? { |key| key =~ expected_key }, "actual '#{actual}' should match '#{expected_key}'"
403
+ expected_key = %r{author/author-\d+}
404
+ assert actual.any? { |key| key =~ expected_key }, "actual '#{actual}' should match '#{expected_key}'"
335
405
  end
336
406
 
407
+ # rubocop:disable Metrics/AbcSize
337
408
  def test_fetch_attributes_from_cache
338
409
  serializers = ActiveModel::Serializer::CollectionSerializer.new([@comment, @comment])
339
410
 
@@ -344,10 +415,10 @@ module ActiveModelSerializers
344
415
  adapter_options = {}
345
416
  adapter_instance = ActiveModelSerializers::Adapter::Attributes.new(serializers, adapter_options)
346
417
  serializers.serializable_hash(adapter_options, options, adapter_instance)
347
- cached_attributes = adapter_options.fetch(:cached_attributes)
418
+ cached_attributes = adapter_options.fetch(:cached_attributes).with_indifferent_access
348
419
 
349
420
  include_directive = ActiveModelSerializers.default_include_directive
350
- manual_cached_attributes = ActiveModel::Serializer.cache_read_multi(serializers, adapter_instance, include_directive)
421
+ manual_cached_attributes = ActiveModel::Serializer.cache_read_multi(serializers, adapter_instance, include_directive).with_indifferent_access
351
422
  assert_equal manual_cached_attributes, cached_attributes
352
423
 
353
424
  assert_equal cached_attributes["#{@comment.cache_key}/#{adapter_instance.cache_key}"], Comment.new(id: 1, body: 'ZOMG A COMMENT').attributes
@@ -358,6 +429,7 @@ module ActiveModelSerializers
358
429
  assert_equal cached_attributes["#{writer_cache_key}/#{adapter_instance.cache_key}"], Author.new(id: 'author', name: 'Joao M. D. Moura').attributes
359
430
  end
360
431
  end
432
+ # rubocop:enable Metrics/AbcSize
361
433
 
362
434
  def test_cache_read_multi_with_fragment_cache_enabled
363
435
  post_serializer = Class.new(ActiveModel::Serializer) do
@@ -516,7 +588,7 @@ module ActiveModelSerializers
516
588
  role_hash = role_serializer.fetch_attributes_fragment(adapter_instance)
517
589
  assert_equal(role_hash, expected_result)
518
590
 
519
- role.attributes[:id] = 'this has been updated'
591
+ role.id = 'this has been updated'
520
592
  role.name = 'this was cached'
521
593
 
522
594
  role_hash = role_serializer.fetch_attributes_fragment(adapter_instance)