active_model_serializers 0.10.0 → 0.10.1

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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -2
  3. data/Gemfile +1 -1
  4. data/README.md +21 -24
  5. data/active_model_serializers.gemspec +4 -8
  6. data/docs/general/adapters.md +4 -2
  7. data/docs/general/configuration_options.md +6 -1
  8. data/docs/general/deserialization.md +1 -1
  9. data/docs/general/serializers.md +30 -3
  10. data/docs/jsonapi/schema.md +1 -1
  11. data/lib/active_model/serializer.rb +54 -11
  12. data/lib/active_model/serializer/adapter/base.rb +2 -0
  13. data/lib/active_model/serializer/associations.rb +4 -5
  14. data/lib/active_model/serializer/belongs_to_reflection.rb +0 -3
  15. data/lib/active_model/serializer/caching.rb +62 -110
  16. data/lib/active_model/serializer/collection_serializer.rb +30 -10
  17. data/lib/active_model/serializer/configuration.rb +1 -0
  18. data/lib/active_model/serializer/has_many_reflection.rb +0 -3
  19. data/lib/active_model/serializer/has_one_reflection.rb +0 -3
  20. data/lib/active_model/serializer/reflection.rb +3 -3
  21. data/lib/active_model/serializer/version.rb +1 -1
  22. data/lib/active_model_serializers.rb +6 -0
  23. data/lib/active_model_serializers/adapter.rb +6 -0
  24. data/lib/active_model_serializers/adapter/attributes.rb +2 -67
  25. data/lib/active_model_serializers/adapter/base.rb +38 -38
  26. data/lib/active_model_serializers/adapter/json_api.rb +36 -28
  27. data/lib/active_model_serializers/adapter/json_api/link.rb +1 -1
  28. data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +8 -1
  29. data/lib/active_model_serializers/deprecate.rb +1 -2
  30. data/lib/active_model_serializers/deserialization.rb +2 -0
  31. data/lib/active_model_serializers/model.rb +2 -0
  32. data/lib/active_model_serializers/railtie.rb +2 -0
  33. data/lib/active_model_serializers/register_jsonapi_renderer.rb +34 -23
  34. data/lib/active_model_serializers/serialization_context.rb +10 -3
  35. data/lib/grape/formatters/active_model_serializers.rb +19 -2
  36. data/lib/grape/helpers/active_model_serializers.rb +1 -0
  37. data/test/action_controller/adapter_selector_test.rb +1 -1
  38. data/test/action_controller/explicit_serializer_test.rb +5 -4
  39. data/test/action_controller/json/include_test.rb +106 -27
  40. data/test/action_controller/json_api/errors_test.rb +2 -2
  41. data/test/action_controller/json_api/linked_test.rb +26 -21
  42. data/test/action_controller/serialization_test.rb +9 -6
  43. data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +143 -0
  44. data/test/active_model_serializers/serialization_context_test_isolated.rb +23 -10
  45. data/test/adapter/json/collection_test.rb +14 -0
  46. data/test/adapter/json_api/collection_test.rb +4 -3
  47. data/test/adapter/json_api/errors_test.rb +13 -15
  48. data/test/adapter/json_api/linked_test.rb +8 -5
  49. data/test/adapter/json_api/links_test.rb +3 -1
  50. data/test/adapter/json_api/pagination_links_test.rb +13 -1
  51. data/test/adapter/json_api/relationships_test.rb +9 -4
  52. data/test/adapter/json_api/resource_identifier_test.rb +7 -2
  53. data/test/adapter/json_api/transform_test.rb +76 -75
  54. data/test/adapter/json_test.rb +4 -3
  55. data/test/benchmark/app.rb +1 -1
  56. data/test/benchmark/bm_caching.rb +14 -14
  57. data/test/benchmark/bm_transform.rb +16 -5
  58. data/test/benchmark/controllers.rb +16 -17
  59. data/test/benchmark/fixtures.rb +72 -72
  60. data/test/cache_test.rb +73 -45
  61. data/test/fixtures/poro.rb +6 -5
  62. data/test/grape_test.rb +96 -2
  63. data/test/serializable_resource_test.rb +12 -12
  64. data/test/serializers/meta_test.rb +12 -6
  65. data/test/support/isolated_unit.rb +1 -0
  66. data/test/support/rails5_shims.rb +8 -2
  67. data/test/support/rails_app.rb +0 -9
  68. metadata +53 -23
  69. data/lib/active_model/serializer/include_tree.rb +0 -111
  70. data/test/include_tree/from_include_args_test.rb +0 -26
  71. data/test/include_tree/from_string_test.rb +0 -94
  72. data/test/include_tree/include_args_to_hash_test.rb +0 -64
@@ -33,9 +33,10 @@ module ActiveModelSerializers
33
33
 
34
34
  assert_equal({
35
35
  id: 1,
36
- reviews: [{ id: 1, body: 'ZOMG A COMMENT' },
37
- { id: 2, body: 'ZOMG ANOTHER COMMENT' }
38
- ],
36
+ reviews: [
37
+ { id: 1, body: 'ZOMG A COMMENT' },
38
+ { id: 2, body: 'ZOMG ANOTHER COMMENT' }
39
+ ],
39
40
  writer: { id: 1, name: 'Steve K.' },
40
41
  site: { id: 1, name: 'My Blog!!' }
41
42
  }, adapter.serializable_hash[:post])
@@ -43,7 +43,7 @@ class BenchmarkApp < Rails::Application
43
43
  config.secret_key_base = 'abc123'
44
44
  config.consider_all_requests_local = false
45
45
 
46
- # otherwise deadlock occured
46
+ # otherwise deadlock occurred
47
47
  config.middleware.delete 'Rack::Lock'
48
48
 
49
49
  # to disable log files
@@ -66,25 +66,25 @@ class ApiAssertion
66
66
  def expected
67
67
  @expected ||=
68
68
  {
69
- 'post' => {
70
- 'id' => 1337,
71
- 'title' => 'New Post',
69
+ 'primary_resource' => {
70
+ 'id' => 1337,
71
+ 'title' => 'New PrimaryResource',
72
72
  'body' => 'Body',
73
- 'comments' => [
74
- {
75
- 'id' => 1,
76
- 'body' => 'ZOMG A COMMENT'
77
- }
78
- ],
79
- 'blog' => {
80
- 'id' => 999,
81
- 'name' => 'Custom blog'
73
+ 'virtual_attribute' => {
74
+ 'id' => 999,
75
+ 'name' => 'Free-Range Virtual Attribute'
82
76
  },
83
- 'author' => {
77
+ 'has_one_relationship' => {
84
78
  'id' => 42,
85
79
  'first_name' => 'Joao',
86
80
  'last_name' => 'Moura'
87
- }
81
+ },
82
+ 'has_many_relationships' => [
83
+ {
84
+ 'id' => 1,
85
+ 'body' => 'ZOMG A HAS MANY RELATIONSHIP'
86
+ }
87
+ ]
88
88
  }
89
89
  }
90
90
  end
@@ -4,12 +4,23 @@ require_relative './app'
4
4
  time = 10
5
5
  disable_gc = true
6
6
  ActiveModelSerializers.config.key_transform = :unaltered
7
- comments = (0..50).map do |i|
8
- Comment.new(id: i, body: 'ZOMG A COMMENT')
7
+ has_many_relationships = (0..50).map do |i|
8
+ HasManyRelationship.new(id: i, body: 'ZOMG A HAS MANY RELATIONSHIP')
9
9
  end
10
- author = Author.new(id: 42, first_name: 'Joao', last_name: 'Moura')
11
- post = Post.new(id: 1337, title: 'New Post', blog: nil, body: 'Body', comments: comments, author: author)
12
- serializer = PostSerializer.new(post)
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)
13
24
  adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer)
14
25
  serialization = adapter.as_json
15
26
 
@@ -1,31 +1,30 @@
1
- class PostController < ActionController::Base
2
- POST =
1
+ class PrimaryResourceController < ActionController::Base
2
+ PRIMARY_RESOURCE =
3
3
  begin
4
- updated_at = Time.current
5
4
  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)
5
+ has_many_relationships = (0..50).map do |i|
6
+ HasManyRelationship.new(id: i, body: 'ZOMG A HAS MANY RELATIONSHIP')
8
7
  end
9
8
  else
10
- comments = [Comment.new(id: 1, body: 'ZOMG A COMMENT', updated_at: updated_at)]
9
+ has_many_relationships = [HasManyRelationship.new(id: 1, body: 'ZOMG A HAS MANY RELATIONSHIP')]
11
10
  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)
11
+ has_one_relationship = HasOneRelationship.new(id: 42, first_name: 'Joao', last_name: 'Moura')
12
+ PrimaryResource.new(id: 1337, title: 'New PrimaryResource', virtual_attribute: nil, body: 'Body', has_many_relationships: has_many_relationships, has_one_relationship: has_one_relationship)
14
13
  end
15
14
 
16
15
  def render_with_caching_serializer
17
16
  toggle_cache_status
18
- render json: POST, serializer: CachingPostSerializer, adapter: :json, meta: { caching: perform_caching }
17
+ render json: PRIMARY_RESOURCE, serializer: CachingPrimaryResourceSerializer, adapter: :json, meta: { caching: perform_caching }
19
18
  end
20
19
 
21
20
  def render_with_fragment_caching_serializer
22
21
  toggle_cache_status
23
- render json: POST, serializer: FragmentCachingPostSerializer, adapter: :json, meta: { caching: perform_caching }
22
+ render json: PRIMARY_RESOURCE, serializer: FragmentCachingPrimaryResourceSerializer, adapter: :json, meta: { caching: perform_caching }
24
23
  end
25
24
 
26
25
  def render_with_non_caching_serializer
27
26
  toggle_cache_status
28
- render json: POST, adapter: :json, meta: { caching: perform_caching }
27
+ render json: PRIMARY_RESOURCE, adapter: :json, meta: { caching: perform_caching }
29
28
  end
30
29
 
31
30
  def render_cache_status
@@ -33,7 +32,7 @@ class PostController < ActionController::Base
33
32
  # Uncomment to debug
34
33
  # STDERR.puts cache_store.class
35
34
  # STDERR.puts cache_dependencies
36
- # ActiveSupport::Cache::Store.logger.debug [ActiveModelSerializers.config.cache_store, ActiveModelSerializers.config.perform_caching, CachingPostSerializer._cache, perform_caching, params].inspect
35
+ # ActiveSupport::Cache::Store.logger.debug [ActiveModelSerializers.config.cache_store, ActiveModelSerializers.config.perform_caching, CachingPrimaryResourceSerializer._cache, perform_caching, params].inspect
37
36
  render json: { caching: perform_caching, meta: { cache_log: cache_messages, cache_status: cache_status } }.to_json
38
37
  end
39
38
 
@@ -76,9 +75,9 @@ class PostController < ActionController::Base
76
75
  end
77
76
 
78
77
  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'
78
+ get '/status(/:on)' => 'primary_resource#render_cache_status'
79
+ get '/clear' => 'primary_resource#clear'
80
+ get '/caching(/:on)' => 'primary_resource#render_with_caching_serializer'
81
+ get '/fragment_caching(/:on)' => 'primary_resource#render_with_fragment_caching_serializer'
82
+ get '/non_caching(/:on)' => 'primary_resource#render_with_non_caching_serializer'
84
83
  end
@@ -1,33 +1,33 @@
1
1
  Rails.configuration.serializers = []
2
- class AuthorSerializer < ActiveModel::Serializer
2
+ class HasOneRelationshipSerializer < ActiveModel::Serializer
3
3
  attributes :id, :first_name, :last_name
4
4
 
5
- has_many :posts, embed: :ids
5
+ has_many :primary_resources, embed: :ids
6
6
  has_one :bio
7
7
  end
8
- Rails.configuration.serializers << AuthorSerializer
8
+ Rails.configuration.serializers << HasOneRelationshipSerializer
9
9
 
10
- class BlogSerializer < ActiveModel::Serializer
10
+ class VirtualAttributeSerializer < ActiveModel::Serializer
11
11
  attributes :id, :name
12
12
  end
13
- Rails.configuration.serializers << BlogSerializer
13
+ Rails.configuration.serializers << VirtualAttributeSerializer
14
14
 
15
- class CommentSerializer < ActiveModel::Serializer
16
- attributes :id, :body, :updated_at
15
+ class HasManyRelationshipSerializer < ActiveModel::Serializer
16
+ attributes :id, :body
17
17
 
18
- belongs_to :post
19
- belongs_to :author
18
+ belongs_to :primary_resource
19
+ belongs_to :has_one_relationship
20
20
  end
21
- Rails.configuration.serializers << CommentSerializer
21
+ Rails.configuration.serializers << HasManyRelationshipSerializer
22
22
 
23
- class PostSerializer < ActiveModel::Serializer
23
+ class PrimaryResourceSerializer < ActiveModel::Serializer
24
24
  attributes :id, :title, :body
25
25
 
26
- has_many :comments, serializer: CommentSerializer
27
- belongs_to :blog, serializer: BlogSerializer
28
- belongs_to :author, serializer: AuthorSerializer
26
+ has_many :has_many_relationships, serializer: HasManyRelationshipSerializer
27
+ belongs_to :virtual_attribute, serializer: VirtualAttributeSerializer
28
+ belongs_to :has_one_relationship, serializer: HasOneRelationshipSerializer
29
29
 
30
- link(:post_authors) { 'https://example.com/post_authors' }
30
+ link(:primary_resource_has_one_relationships) { 'https://example.com/primary_resource_has_one_relationships' }
31
31
 
32
32
  meta do
33
33
  {
@@ -36,33 +36,33 @@ class PostSerializer < ActiveModel::Serializer
36
36
  }
37
37
  end
38
38
 
39
- def blog
40
- Blog.new(id: 999, name: 'Custom blog')
39
+ def virtual_attribute
40
+ VirtualAttribute.new(id: 999, name: 'Free-Range Virtual Attribute')
41
41
  end
42
42
  end
43
- Rails.configuration.serializers << PostSerializer
43
+ Rails.configuration.serializers << PrimaryResourceSerializer
44
44
 
45
- class CachingAuthorSerializer < AuthorSerializer
45
+ class CachingHasOneRelationshipSerializer < HasOneRelationshipSerializer
46
46
  cache key: 'writer', skip_digest: true
47
47
  end
48
- Rails.configuration.serializers << CachingAuthorSerializer
48
+ Rails.configuration.serializers << CachingHasOneRelationshipSerializer
49
49
 
50
- class CachingCommentSerializer < CommentSerializer
50
+ class CachingHasManyRelationshipSerializer < HasManyRelationshipSerializer
51
51
  cache expires_in: 1.day, skip_digest: true
52
52
  end
53
- Rails.configuration.serializers << CachingCommentSerializer
53
+ Rails.configuration.serializers << CachingHasManyRelationshipSerializer
54
54
 
55
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
56
+ class CachingPrimaryResourceSerializer < ActiveModel::Serializer
57
+ cache key: 'primary_resource', expires_in: 0.1, skip_digest: true
58
58
 
59
59
  attributes :id, :title, :body
60
60
 
61
- belongs_to :blog, serializer: BlogSerializer
62
- belongs_to :author, serializer: CachingAuthorSerializer
63
- has_many :comments, serializer: CachingCommentSerializer
61
+ belongs_to :virtual_attribute, serializer: VirtualAttributeSerializer
62
+ belongs_to :has_one_relationship, serializer: CachingHasOneRelationshipSerializer
63
+ has_many :has_many_relationships, serializer: CachingHasManyRelationshipSerializer
64
64
 
65
- link(:post_authors) { 'https://example.com/post_authors' }
65
+ link(:primary_resource_has_one_relationships) { 'https://example.com/primary_resource_has_one_relationships' }
66
66
 
67
67
  meta do
68
68
  {
@@ -71,33 +71,33 @@ class CachingPostSerializer < ActiveModel::Serializer
71
71
  }
72
72
  end
73
73
 
74
- def blog
75
- Blog.new(id: 999, name: 'Custom blog')
74
+ def virtual_attribute
75
+ VirtualAttribute.new(id: 999, name: 'Free-Range Virtual Attribute')
76
76
  end
77
77
  end
78
- Rails.configuration.serializers << CachingPostSerializer
78
+ Rails.configuration.serializers << CachingPrimaryResourceSerializer
79
79
 
80
- class FragmentCachingAuthorSerializer < AuthorSerializer
80
+ class FragmentCachingHasOneRelationshipSerializer < HasOneRelationshipSerializer
81
81
  cache key: 'writer', only: [:first_name, :last_name], skip_digest: true
82
82
  end
83
- Rails.configuration.serializers << FragmentCachingAuthorSerializer
83
+ Rails.configuration.serializers << FragmentCachingHasOneRelationshipSerializer
84
84
 
85
- class FragmentCachingCommentSerializer < CommentSerializer
86
- cache expires_in: 1.day, except: [:updated_at], skip_digest: true
85
+ class FragmentCachingHasManyRelationshipSerializer < HasManyRelationshipSerializer
86
+ cache expires_in: 1.day, except: [:body], skip_digest: true
87
87
  end
88
- Rails.configuration.serializers << CachingCommentSerializer
88
+ Rails.configuration.serializers << CachingHasManyRelationshipSerializer
89
89
 
90
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
91
+ class FragmentCachingPrimaryResourceSerializer < ActiveModel::Serializer
92
+ cache key: 'primary_resource', expires_in: 0.1, skip_digest: true
93
93
 
94
94
  attributes :id, :title, :body
95
95
 
96
- belongs_to :blog, serializer: BlogSerializer
97
- belongs_to :author, serializer: FragmentCachingAuthorSerializer
98
- has_many :comments, serializer: FragmentCachingCommentSerializer
96
+ belongs_to :virtual_attribute, serializer: VirtualAttributeSerializer
97
+ belongs_to :has_one_relationship, serializer: FragmentCachingHasOneRelationshipSerializer
98
+ has_many :has_many_relationships, serializer: FragmentCachingHasManyRelationshipSerializer
99
99
 
100
- link(:post_authors) { 'https://example.com/post_authors' }
100
+ link(:primary_resource_has_one_relationships) { 'https://example.com/primary_resource_has_one_relationships' }
101
101
 
102
102
  meta do
103
103
  {
@@ -106,11 +106,11 @@ class FragmentCachingPostSerializer < ActiveModel::Serializer
106
106
  }
107
107
  end
108
108
 
109
- def blog
110
- Blog.new(id: 999, name: 'Custom blog')
109
+ def virtual_attribute
110
+ VirtualAttribute.new(id: 999, name: 'Free-Range Virtual Attribute')
111
111
  end
112
112
  end
113
- Rails.configuration.serializers << FragmentCachingPostSerializer
113
+ Rails.configuration.serializers << FragmentCachingPrimaryResourceSerializer
114
114
 
115
115
  if ENV['ENABLE_ACTIVE_RECORD'] == 'true'
116
116
  require 'active_record'
@@ -119,48 +119,48 @@ if ENV['ENABLE_ACTIVE_RECORD'] == 'true'
119
119
  ActiveRecord::Schema.define do
120
120
  self.verbose = false
121
121
 
122
- create_table :blogs, force: true do |t|
122
+ create_table :virtual_attributes, force: true do |t|
123
123
  t.string :name
124
124
  t.timestamps null: false
125
125
  end
126
- create_table :authors, force: true do |t|
126
+ create_table :has_one_relationships, force: true do |t|
127
127
  t.string :first_name
128
128
  t.string :last_name
129
129
  t.timestamps null: false
130
130
  end
131
- create_table :posts, force: true do |t|
131
+ create_table :primary_resources, force: true do |t|
132
132
  t.string :title
133
133
  t.text :body
134
- t.references :author
135
- t.references :blog
134
+ t.references :has_one_relationship
135
+ t.references :virtual_attribute
136
136
  t.timestamps null: false
137
137
  end
138
- create_table :comments, force: true do |t|
138
+ create_table :has_many_relationships, force: true do |t|
139
139
  t.text :body
140
- t.references :author
141
- t.references :post
140
+ t.references :has_one_relationship
141
+ t.references :primary_resource
142
142
  t.timestamps null: false
143
143
  end
144
144
  end
145
145
 
146
- class Comment < ActiveRecord::Base
147
- belongs_to :author
148
- belongs_to :post
146
+ class HasManyRelationship < ActiveRecord::Base
147
+ belongs_to :has_one_relationship
148
+ belongs_to :primary_resource
149
149
  end
150
150
 
151
- class Author < ActiveRecord::Base
152
- has_many :posts
153
- has_many :comments
151
+ class HasOneRelationship < ActiveRecord::Base
152
+ has_many :primary_resources
153
+ has_many :has_many_relationships
154
154
  end
155
155
 
156
- class Post < ActiveRecord::Base
157
- has_many :comments
158
- belongs_to :author
159
- belongs_to :blog
156
+ class PrimaryResource < ActiveRecord::Base
157
+ has_many :has_many_relationships
158
+ belongs_to :has_one_relationship
159
+ belongs_to :virtual_attribute
160
160
  end
161
161
 
162
- class Blog < ActiveRecord::Base
163
- has_many :posts
162
+ class VirtualAttribute < ActiveRecord::Base
163
+ has_many :primary_resources
164
164
  end
165
165
  else
166
166
  # ActiveModelSerializers::Model is a convenient
@@ -201,19 +201,19 @@ else
201
201
  end
202
202
  end
203
203
 
204
- class Comment < BenchmarkModel
205
- attr_accessor :id, :body, :updated_at
204
+ class HasManyRelationship < BenchmarkModel
205
+ attr_accessor :id, :body
206
206
  end
207
207
 
208
- class Author < BenchmarkModel
209
- attr_accessor :id, :first_name, :last_name, :posts
208
+ class HasOneRelationship < BenchmarkModel
209
+ attr_accessor :id, :first_name, :last_name, :primary_resources
210
210
  end
211
211
 
212
- class Post < BenchmarkModel
213
- attr_accessor :id, :title, :body, :comments, :blog, :author
212
+ class PrimaryResource < BenchmarkModel
213
+ attr_accessor :id, :title, :body, :has_many_relationships, :virtual_attribute, :has_one_relationship
214
214
  end
215
215
 
216
- class Blog < BenchmarkModel
216
+ class VirtualAttribute < BenchmarkModel
217
217
  attr_accessor :id, :name
218
218
  end
219
219
  end
@@ -102,13 +102,13 @@ module ActiveModelSerializers
102
102
 
103
103
  render_object_with_cache(uncached_author)
104
104
  key = "#{uncached_author_serializer.class._cache_key}/#{uncached_author_serializer.object.id}-#{uncached_author_serializer.object.updated_at.strftime("%Y%m%d%H%M%S%9N")}"
105
- key = "#{key}/#{adapter.cached_name}"
105
+ key = "#{key}/#{adapter.cache_key}"
106
106
  assert_equal(uncached_author_serializer.attributes.to_json, cache_store.fetch(key).to_json)
107
107
  end
108
108
 
109
109
  def test_default_cache_key_fallback
110
110
  render_object_with_cache(@comment)
111
- key = "#{@comment.cache_key}/#{adapter.cached_name}"
111
+ key = "#{@comment.cache_key}/#{adapter.cache_key}"
112
112
  assert_equal(@comment_serializer.attributes.to_json, cache_store.fetch(key).to_json)
113
113
  end
114
114
 
@@ -117,7 +117,7 @@ module ActiveModelSerializers
117
117
  e = assert_raises ActiveModel::Serializer::UndefinedCacheKey do
118
118
  render_object_with_cache(article)
119
119
  end
120
- assert_match(/ActiveModelSerializers::CacheTest::Article must define #cache_key, or the 'key:' option must be passed into 'CachedActiveModelSerializers_CacheTest_ArticleSerializer.cache'/, e.message)
120
+ assert_match(/ActiveModelSerializers::CacheTest::Article must define #cache_key, or the 'key:' option must be passed into 'ActiveModelSerializers::CacheTest::ArticleSerializer.cache'/, e.message)
121
121
  end
122
122
 
123
123
  def test_cache_options_definition
@@ -127,7 +127,7 @@ module ActiveModelSerializers
127
127
  end
128
128
 
129
129
  def test_fragment_cache_definition
130
- assert_equal([:name], @role_serializer.class._cache_only)
130
+ assert_equal([:name, :slug], @role_serializer.class._cache_only)
131
131
  assert_equal([:content], @bio_serializer.class._cache_except)
132
132
  end
133
133
 
@@ -139,9 +139,9 @@ module ActiveModelSerializers
139
139
  Timecop.freeze(Time.current) do
140
140
  render_object_with_cache(@post)
141
141
 
142
- key = "#{@post.cache_key}/#{adapter.cached_name}"
142
+ key = "#{@post.cache_key}/#{adapter.cache_key}"
143
143
  assert_equal(@post_serializer.attributes, cache_store.fetch(key))
144
- key = "#{@comment.cache_key}/#{adapter.cached_name}"
144
+ key = "#{@comment.cache_key}/#{adapter.cache_key}"
145
145
  assert_equal(@comment_serializer.attributes, cache_store.fetch(key))
146
146
  end
147
147
  end
@@ -152,9 +152,9 @@ module ActiveModelSerializers
152
152
  render_object_with_cache(@post)
153
153
 
154
154
  # Check if it cached the objects separately
155
- key = "#{@post.cache_key}/#{adapter.cached_name}"
155
+ key = "#{@post.cache_key}/#{adapter.cache_key}"
156
156
  assert_equal(@post_serializer.attributes, cache_store.fetch(key))
157
- key = "#{@comment.cache_key}/#{adapter.cached_name}"
157
+ key = "#{@comment.cache_key}/#{adapter.cache_key}"
158
158
  assert_equal(@comment_serializer.attributes, cache_store.fetch(key))
159
159
 
160
160
  # Simulating update on comments relationship with Post
@@ -166,9 +166,9 @@ module ActiveModelSerializers
166
166
  render_object_with_cache(@post)
167
167
 
168
168
  # Check if the the new comment was cached
169
- key = "#{new_comment.cache_key}/#{adapter.cached_name}"
169
+ key = "#{new_comment.cache_key}/#{adapter.cache_key}"
170
170
  assert_equal(new_comment_serializer.attributes, cache_store.fetch(key))
171
- key = "#{@post.cache_key}/#{adapter.cached_name}"
171
+ key = "#{@post.cache_key}/#{adapter.cache_key}"
172
172
  assert_equal(@post_serializer.attributes, cache_store.fetch(key))
173
173
  end
174
174
  end
@@ -178,14 +178,14 @@ module ActiveModelSerializers
178
178
  id: @location.id,
179
179
  lat: @location.lat,
180
180
  lng: @location.lng,
181
- place: 'Nowhere'
181
+ address: 'Nowhere'
182
182
  }
183
183
 
184
184
  hash = render_object_with_cache(@location)
185
185
 
186
186
  assert_equal(hash, expected_result)
187
- key = "#{@location.cache_key}/#{adapter.cached_name}"
188
- assert_equal({ place: 'Nowhere' }, cache_store.fetch(key))
187
+ key = "#{@location.cache_key}/#{adapter.cache_key}"
188
+ assert_equal({ address: 'Nowhere' }, cache_store.fetch(key))
189
189
  end
190
190
 
191
191
  def test_fragment_cache_with_inheritance
@@ -204,7 +204,7 @@ module ActiveModelSerializers
204
204
 
205
205
  # Based on original failing test by @kevintyll
206
206
  # rubocop:disable Metrics/AbcSize
207
- def test_a_serializer_rendered_by_two_adapter_returns_differently_cached_attributes
207
+ def test_a_serializer_rendered_by_two_adapter_returns_differently_fetch_attributes
208
208
  Object.const_set(:Alert, Class.new(ActiveModelSerializers::Model) do
209
209
  attr_accessor :id, :status, :resource, :started_at, :ended_at, :updated_at, :created_at
210
210
  end)
@@ -225,7 +225,7 @@ module ActiveModelSerializers
225
225
  created_at: Time.new(2016, 3, 31, 21, 37, 35, 0)
226
226
  )
227
227
 
228
- expected_cached_attributes = {
228
+ expected_fetch_attributes = {
229
229
  id: 1,
230
230
  status: 'fail',
231
231
  resource: 'resource-1',
@@ -250,7 +250,7 @@ module ActiveModelSerializers
250
250
  # Assert attributes are serialized correctly
251
251
  serializable_alert = serializable(alert, serializer: AlertSerializer, adapter: :attributes)
252
252
  attributes_serialization = serializable_alert.as_json
253
- assert_equal expected_cached_attributes, alert.attributes
253
+ assert_equal expected_fetch_attributes, alert.attributes
254
254
  assert_equal alert.attributes, attributes_serialization
255
255
  attributes_cache_key = serializable_alert.adapter.serializer.cache_key(serializable_alert.adapter)
256
256
  assert_equal attributes_serialization, cache_store.fetch(attributes_cache_key)
@@ -276,7 +276,7 @@ module ActiveModelSerializers
276
276
 
277
277
  def test_uses_file_digest_in_cache_key
278
278
  render_object_with_cache(@blog)
279
- key = "#{@blog.cache_key}/#{adapter.cached_name}/#{::Model::FILE_DIGEST}"
279
+ key = "#{@blog.cache_key}/#{adapter.cache_key}/#{::Model::FILE_DIGEST}"
280
280
  assert_equal(@blog_serializer.attributes, cache_store.fetch(key))
281
281
  end
282
282
 
@@ -286,33 +286,38 @@ module ActiveModelSerializers
286
286
 
287
287
  def test_object_cache_keys
288
288
  serializable = ActiveModelSerializers::SerializableResource.new([@comment, @comment])
289
- include_tree = ActiveModel::Serializer::IncludeTree.from_include_args('*')
289
+ include_directive = JSONAPI::IncludeDirective.new('*', allow_wildcard: true)
290
290
 
291
- actual = ActiveModel::Serializer.object_cache_keys(serializable.adapter.serializer, serializable.adapter, include_tree)
291
+ actual = ActiveModel::Serializer.object_cache_keys(serializable.adapter.serializer, serializable.adapter, include_directive)
292
292
 
293
293
  assert_equal 3, actual.size
294
- assert actual.any? { |key| key == "comment/1/#{serializable.adapter.cached_name}" }
294
+ assert actual.any? { |key| key == "comment/1/#{serializable.adapter.cache_key}" }
295
295
  assert actual.any? { |key| key =~ %r{post/post-\d+} }
296
296
  assert actual.any? { |key| key =~ %r{author/author-\d+} }
297
297
  end
298
298
 
299
- def test_cached_attributes
300
- serializer = ActiveModel::Serializer::CollectionSerializer.new([@comment, @comment])
299
+ def test_fetch_attributes_from_cache
300
+ serializers = ActiveModel::Serializer::CollectionSerializer.new([@comment, @comment])
301
301
 
302
302
  Timecop.freeze(Time.current) do
303
303
  render_object_with_cache(@comment)
304
304
 
305
- attributes = Adapter::Attributes.new(serializer)
306
- attributes.send(:cache_attributes)
307
- cached_attributes = attributes.instance_variable_get(:@cached_attributes)
305
+ options = {}
306
+ adapter_options = {}
307
+ adapter_instance = ActiveModelSerializers::Adapter::Attributes.new(serializers, adapter_options)
308
+ serializers.serializable_hash(adapter_options, options, adapter_instance)
309
+ cached_attributes = adapter_options.fetch(:cached_attributes)
308
310
 
309
- assert_equal cached_attributes["#{@comment.cache_key}/#{attributes.cached_name}"], Comment.new(id: 1, body: 'ZOMG A COMMENT').attributes
310
- assert_equal cached_attributes["#{@comment.post.cache_key}/#{attributes.cached_name}"], Post.new(id: 'post', title: 'New Post', body: 'Body').attributes
311
+ include_directive = ActiveModelSerializers.default_include_directive
312
+ manual_cached_attributes = ActiveModel::Serializer.cache_read_multi(serializers, adapter_instance, include_directive)
313
+ assert_equal manual_cached_attributes, cached_attributes
314
+
315
+ assert_equal cached_attributes["#{@comment.cache_key}/#{adapter_instance.cache_key}"], Comment.new(id: 1, body: 'ZOMG A COMMENT').attributes
316
+ assert_equal cached_attributes["#{@comment.post.cache_key}/#{adapter_instance.cache_key}"], Post.new(id: 'post', title: 'New Post', body: 'Body').attributes
311
317
 
312
318
  writer = @comment.post.blog.writer
313
319
  writer_cache_key = writer.cache_key
314
-
315
- assert_equal cached_attributes["#{writer_cache_key}/#{attributes.cached_name}"], Author.new(id: 'author', name: 'Joao M. D. Moura').attributes
320
+ assert_equal cached_attributes["#{writer_cache_key}/#{adapter_instance.cache_key}"], Author.new(id: 'author', name: 'Joao M. D. Moura').attributes
316
321
  end
317
322
  end
318
323
 
@@ -429,25 +434,53 @@ module ActiveModelSerializers
429
434
  end
430
435
 
431
436
  def test_fragment_fetch_with_virtual_attributes
432
- @author = Author.new(name: 'Joao M. D. Moura')
433
- @role = Role.new(name: 'Great Author', description: nil)
434
- @role.author = [@author]
435
- @role_serializer = RoleSerializer.new(@role)
436
- @role_hash = @role_serializer.fetch_fragment_cache(ActiveModelSerializers::Adapter.configured_adapter.new(@role_serializer))
437
+ author = Author.new(name: 'Joao M. D. Moura')
438
+ role = Role.new(name: 'Great Author', description: nil)
439
+ role.author = [author]
440
+ role_serializer = RoleSerializer.new(role)
441
+ adapter_instance = ActiveModelSerializers::Adapter.configured_adapter.new(role_serializer)
442
+ expected_result = {
443
+ id: role.id,
444
+ description: role.description,
445
+ slug: "#{role.name}-#{role.id}",
446
+ name: role.name
447
+ }
448
+ cache_store.clear
449
+
450
+ role_hash = role_serializer.fetch_attributes_fragment(adapter_instance)
451
+ assert_equal(role_hash, expected_result)
437
452
 
453
+ role.attributes[:id] = 'this has been updated'
454
+ role.name = 'this was cached'
455
+
456
+ role_hash = role_serializer.fetch_attributes_fragment(adapter_instance)
457
+ assert_equal(expected_result.merge(id: role.id), role_hash)
458
+ end
459
+
460
+ def test_fragment_fetch_with_except
461
+ adapter_instance = ActiveModelSerializers::Adapter.configured_adapter.new(@bio_serializer)
438
462
  expected_result = {
439
- id: @role.id,
440
- description: @role.description,
441
- slug: "#{@role.name}-#{@role.id}",
442
- name: @role.name
463
+ id: @bio.id,
464
+ rating: nil,
465
+ content: @bio.content
443
466
  }
444
- assert_equal(@role_hash, expected_result)
467
+ cache_store.clear
468
+
469
+ bio_hash = @bio_serializer.fetch_attributes_fragment(adapter_instance)
470
+ assert_equal(expected_result, bio_hash)
471
+
472
+ @bio.content = 'this has been updated'
473
+ @bio.rating = 'this was cached'
474
+
475
+ bio_hash = @bio_serializer.fetch_attributes_fragment(adapter_instance)
476
+ assert_equal(expected_result.merge(content: @bio.content), bio_hash)
445
477
  end
446
478
 
447
479
  def test_fragment_fetch_with_namespaced_object
448
480
  @spam = Spam::UnrelatedLink.new(id: 'spam-id-1')
449
481
  @spam_serializer = Spam::UnrelatedLinkSerializer.new(@spam)
450
- @spam_hash = @spam_serializer.fetch_fragment_cache(ActiveModelSerializers::Adapter.configured_adapter.new(@spam_serializer))
482
+ adapter_instance = ActiveModelSerializers::Adapter.configured_adapter.new(@spam_serializer)
483
+ @spam_hash = @spam_serializer.fetch_attributes_fragment(adapter_instance)
451
484
  expected_result = {
452
485
  id: @spam.id
453
486
  }
@@ -476,10 +509,5 @@ module ActiveModelSerializers
476
509
  def adapter
477
510
  @serializable_resource.adapter
478
511
  end
479
-
480
- def cached_serialization(serializer)
481
- cache_key = serializer.cache_key(adapter)
482
- cache_store.fetch(cache_key)
483
- end
484
512
  end
485
513
  end