active_model_serializers 0.10.4 → 0.10.5

Sign up to get free protection for your applications and to get access to all the features.
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)