active_model_serializers 0.10.0 → 0.10.1

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