active_model_serializers 0.10.0.rc1 → 0.10.0.rc2

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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -2
  3. data/Gemfile +1 -1
  4. data/README.md +6 -3
  5. data/lib/action_controller/serialization.rb +9 -1
  6. data/lib/active_model/serializer.rb +15 -21
  7. data/lib/active_model/serializer/adapter.rb +13 -4
  8. data/lib/active_model/serializer/adapter/flatten_json.rb +12 -0
  9. data/lib/active_model/serializer/adapter/fragment_cache.rb +5 -5
  10. data/lib/active_model/serializer/adapter/json.rb +8 -10
  11. data/lib/active_model/serializer/adapter/json_api.rb +34 -30
  12. data/lib/active_model/serializer/adapter/json_api/fragment_cache.rb +3 -2
  13. data/lib/active_model/serializer/array_serializer.rb +8 -5
  14. data/lib/active_model/serializer/configuration.rb +1 -1
  15. data/lib/active_model/serializer/fieldset.rb +2 -2
  16. data/lib/active_model/serializer/railtie.rb +8 -0
  17. data/lib/active_model/serializer/version.rb +1 -1
  18. data/lib/active_model_serializers.rb +1 -0
  19. data/lib/generators/serializer/resource_override.rb +12 -0
  20. data/test/action_controller/adapter_selector_test.rb +7 -5
  21. data/test/action_controller/explicit_serializer_test.rb +33 -9
  22. data/test/action_controller/json_api_linked_test.rb +25 -19
  23. data/test/action_controller/rescue_from_test.rb +32 -0
  24. data/test/action_controller/serialization_scope_name_test.rb +2 -2
  25. data/test/action_controller/serialization_test.rb +41 -23
  26. data/test/adapter/fragment_cache_test.rb +1 -1
  27. data/test/adapter/json/belongs_to_test.rb +9 -2
  28. data/test/adapter/json/collection_test.rb +16 -2
  29. data/test/adapter/json/has_many_test.rb +1 -1
  30. data/test/adapter/json_api/belongs_to_test.rb +45 -35
  31. data/test/adapter/json_api/collection_test.rb +30 -23
  32. data/test/adapter/json_api/has_many_embed_ids_test.rb +2 -2
  33. data/test/adapter/json_api/has_many_explicit_serializer_test.rb +14 -14
  34. data/test/adapter/json_api/has_many_test.rb +22 -18
  35. data/test/adapter/json_api/has_one_test.rb +8 -6
  36. data/test/adapter/json_api/linked_test.rb +97 -71
  37. data/test/adapter/json_test.rb +1 -1
  38. data/test/adapter_test.rb +1 -1
  39. data/test/array_serializer_test.rb +14 -0
  40. data/test/fixtures/poro.rb +31 -7
  41. data/test/generators/scaffold_controller_generator_test.rb +24 -0
  42. data/test/{serializers/generators_test.rb → generators/serializer_generator_test.rb} +2 -10
  43. data/test/serializers/adapter_for_test.rb +1 -1
  44. data/test/serializers/associations_test.rb +21 -0
  45. data/test/serializers/attribute_test.rb +16 -1
  46. data/test/serializers/attributes_test.rb +35 -0
  47. data/test/serializers/cache_test.rb +14 -4
  48. data/test/serializers/configuration_test.rb +1 -1
  49. data/test/serializers/meta_test.rb +38 -9
  50. data/test/serializers/serializer_for_test.rb +9 -0
  51. data/test/test_helper.rb +10 -7
  52. metadata +12 -5
@@ -30,9 +30,9 @@ module ActiveModel
30
30
  end
31
31
 
32
32
  def test_includes_bio_id
33
- expected = { linkage: { type: "bios", id: "43" } }
33
+ expected = { data: { type: "bios", id: "43" } }
34
34
 
35
- assert_equal(expected, @adapter.serializable_hash[:data][:links][:bio])
35
+ assert_equal(expected, @adapter.serializable_hash[:data][:relationships][:bio])
36
36
  end
37
37
 
38
38
  def test_includes_linked_bio
@@ -41,11 +41,13 @@ module ActiveModel
41
41
  expected = [
42
42
  {
43
43
  id: "43",
44
- rating: nil,
45
44
  type: "bios",
46
- content:"AMS Contributor",
47
- links: {
48
- author: { linkage: { type: "authors", id: "1" } }
45
+ attributes: {
46
+ content:"AMS Contributor",
47
+ rating: nil
48
+ },
49
+ relationships: {
50
+ author: { data: { type: "authors", id: "1" } }
49
51
  }
50
52
  }
51
53
  ]
@@ -54,77 +54,93 @@ module ActiveModel
54
54
  data: [
55
55
  {
56
56
  id: "10",
57
- title: "Hello!!",
58
- body: "Hello, world!!",
59
57
  type: "posts",
60
- links: {
61
- comments: { linkage: [ { type: "comments", id: '1' }, { type: "comments", id: '2' } ] },
62
- blog: { linkage: { type: "blogs", id: "999" } },
63
- author: { linkage: { type: "authors", id: "1" } }
58
+ attributes: {
59
+ title: "Hello!!",
60
+ body: "Hello, world!!"
61
+ },
62
+ relationships: {
63
+ comments: { data: [ { type: "comments", id: '1' }, { type: "comments", id: '2' } ] },
64
+ blog: { data: { type: "blogs", id: "999" } },
65
+ author: { data: { type: "authors", id: "1" } }
64
66
  }
65
67
  },
66
68
  {
67
69
  id: "20",
68
- title: "New Post",
69
- body: "Body",
70
70
  type: "posts",
71
- links: {
72
- comments: { linkage: [] },
73
- blog: { linkage: { type: "blogs", id: "999" } },
74
- author: { linkage: { type: "authors", id: "2" } }
71
+ attributes: {
72
+ title: "New Post",
73
+ body: "Body"
74
+ },
75
+ relationships: {
76
+ comments: { data: [] },
77
+ blog: { data: { type: "blogs", id: "999" } },
78
+ author: { data: { type: "authors", id: "2" } }
75
79
  }
76
80
  }
77
81
  ],
78
82
  included: [
79
83
  {
80
84
  id: "1",
81
- body: "ZOMG A COMMENT",
82
85
  type: "comments",
83
- links: {
84
- post: { linkage: { type: "posts", id: "10" } },
85
- author: { linkage: nil }
86
+ attributes: {
87
+ body: "ZOMG A COMMENT"
88
+ },
89
+ relationships: {
90
+ post: { data: { type: "posts", id: "10" } },
91
+ author: { data: nil }
86
92
  }
87
93
  }, {
88
94
  id: "2",
89
- body: "ZOMG ANOTHER COMMENT",
90
95
  type: "comments",
91
- links: {
92
- post: { linkage: { type: "posts", id: "10" } },
93
- author: { linkage: nil }
96
+ attributes: {
97
+ body: "ZOMG ANOTHER COMMENT",
98
+ },
99
+ relationships: {
100
+ post: { data: { type: "posts", id: "10" } },
101
+ author: { data: nil }
94
102
  }
95
103
  }, {
96
104
  id: "1",
97
- name: "Steve K.",
98
105
  type: "authors",
99
- links: {
100
- posts: { linkage: [ { type: "posts", id: "10" }, { type: "posts", id: "30" } ] },
101
- roles: { linkage: [] },
102
- bio: { linkage: { type: "bios", id: "1" } }
106
+ attributes: {
107
+ name: "Steve K."
108
+ },
109
+ relationships: {
110
+ posts: { data: [ { type: "posts", id: "10" }, { type: "posts", id: "30" } ] },
111
+ roles: { data: [] },
112
+ bio: { data: { type: "bios", id: "1" } }
103
113
  }
104
114
  }, {
105
115
  id: "1",
106
- rating: nil,
107
116
  type: "bios",
108
- content: "AMS Contributor",
109
- links: {
110
- author: { linkage: { type: "authors", id: "1" } }
117
+ attributes: {
118
+ content: "AMS Contributor",
119
+ rating: nil
120
+ },
121
+ relationships: {
122
+ author: { data: { type: "authors", id: "1" } }
111
123
  }
112
124
  }, {
113
125
  id: "2",
114
- name: "Tenderlove",
115
126
  type: "authors",
116
- links: {
117
- posts: { linkage: [ { type: "posts", id:"20" } ] },
118
- roles: { linkage: [] },
119
- bio: { linkage: { type: "bios", id: "2" } }
127
+ attributes: {
128
+ name: "Tenderlove"
129
+ },
130
+ relationships: {
131
+ posts: { data: [ { type: "posts", id:"20" } ] },
132
+ roles: { data: [] },
133
+ bio: { data: { type: "bios", id: "2" } }
120
134
  }
121
135
  }, {
122
136
  id: "2",
123
- rating: nil,
124
137
  type: "bios",
125
- content: "Rails Contributor",
126
- links: {
127
- author: { linkage: { type: "authors", id: "2" } }
138
+ attributes: {
139
+ rating: nil,
140
+ content: "Rails Contributor",
141
+ },
142
+ relationships: {
143
+ author: { data: { type: "authors", id: "2" } }
128
144
  }
129
145
  }
130
146
  ]
@@ -148,31 +164,37 @@ module ActiveModel
148
164
  {
149
165
  id: "1",
150
166
  type: "authors",
151
- name: "Steve K.",
152
- links: {
153
- posts: { linkage: [ { type: "posts", id: "10"}, { type: "posts", id: "30" }] },
154
- roles: { linkage: [] },
155
- bio: { linkage: { type: "bios", id: "1" }}
167
+ attributes: {
168
+ name: "Steve K."
169
+ },
170
+ relationships: {
171
+ posts: { data: [ { type: "posts", id: "10"}, { type: "posts", id: "30" }] },
172
+ roles: { data: [] },
173
+ bio: { data: { type: "bios", id: "1" }}
156
174
  }
157
175
  }, {
158
176
  id: "10",
159
177
  type: "posts",
160
- title: "Hello!!",
161
- body: "Hello, world!!",
162
- links: {
163
- comments: { linkage: [ { type: "comments", id: "1"}, { type: "comments", id: "2" }] },
164
- blog: { linkage: { type: "blogs", id: "999" } },
165
- author: { linkage: { type: "authors", id: "1" } }
178
+ attributes: {
179
+ title: "Hello!!",
180
+ body: "Hello, world!!"
181
+ },
182
+ relationships: {
183
+ comments: { data: [ { type: "comments", id: "1"}, { type: "comments", id: "2" }] },
184
+ blog: { data: { type: "blogs", id: "999" } },
185
+ author: { data: { type: "authors", id: "1" } }
166
186
  }
167
187
  }, {
168
188
  id: "30",
169
189
  type: "posts",
170
- title: "Yet Another Post",
171
- body: "Body",
172
- links: {
173
- comments: { linkage: [] },
174
- blog: { linkage: { type: "blogs", id: "999" } },
175
- author: { linkage: { type: "authors", id: "1" } }
190
+ attributes: {
191
+ title: "Yet Another Post",
192
+ body: "Body"
193
+ },
194
+ relationships: {
195
+ comments: { data: [] },
196
+ blog: { data: { type: "blogs", id: "999" } },
197
+ author: { data: { type: "authors", id: "1" } }
176
198
  }
177
199
  }
178
200
  ]
@@ -181,21 +203,21 @@ module ActiveModel
181
203
  assert_equal expected, alt_adapter.serializable_hash[:included]
182
204
  end
183
205
 
184
- def test_ignore_model_namespace_for_linked_resource_type
206
+ def test_underscore_model_namespace_for_linked_resource_type
185
207
  spammy_post = Post.new(id: 123)
186
208
  spammy_post.related = [Spam::UnrelatedLink.new(id: 456)]
187
209
  serializer = SpammyPostSerializer.new(spammy_post)
188
210
  adapter = ActiveModel::Serializer::Adapter::JsonApi.new(serializer)
189
- links = adapter.serializable_hash[:data][:links]
211
+ relationships = adapter.serializable_hash[:data][:relationships]
190
212
  expected = {
191
213
  related: {
192
- linkage: [{
193
- type: 'unrelated_links',
214
+ data: [{
215
+ type: 'spam_unrelated_links',
194
216
  id: '456'
195
217
  }]
196
218
  }
197
219
  }
198
- assert_equal expected, links
220
+ assert_equal expected, relationships
199
221
  end
200
222
 
201
223
  def test_multiple_references_to_same_resource
@@ -208,18 +230,20 @@ module ActiveModel
208
230
  expected = [
209
231
  {
210
232
  id: "10",
211
- title: "Hello!!",
212
- body: "Hello, world!!",
213
233
  type: "posts",
214
- links: {
234
+ attributes: {
235
+ title: "Hello!!",
236
+ body: "Hello, world!!"
237
+ },
238
+ relationships: {
215
239
  comments: {
216
- linkage: [{type: "comments", id: "1"}, {type: "comments", id: "2"}]
240
+ data: [{type: "comments", id: "1"}, {type: "comments", id: "2"}]
217
241
  },
218
242
  blog: {
219
- linkage: {type: "blogs", id: "999"}
243
+ data: {type: "blogs", id: "999"}
220
244
  },
221
245
  author: {
222
- linkage: {type: "authors", id: "1"}
246
+ data: {type: "authors", id: "1"}
223
247
  }
224
248
  }
225
249
  }
@@ -239,12 +263,14 @@ module ActiveModel
239
263
  expected = {
240
264
  data: {
241
265
  id: "10",
242
- title: "Hello!!",
243
- body: "Hello, world!!",
244
266
  type: "posts",
245
- links: {
246
- comments: { linkage: [ { type: "comments", id: '1' }, { type: "comments", id: '2' } ] },
247
- author: { linkage: nil }
267
+ attributes: {
268
+ title: "Hello!!",
269
+ body: "Hello, world!!"
270
+ },
271
+ relationships: {
272
+ comments: { data: [ { type: "comments", id: '1' }, { type: "comments", id: '2' } ] },
273
+ author: { data: nil }
248
274
  }
249
275
  }
250
276
  }
@@ -25,7 +25,7 @@ module ActiveModel
25
25
  assert_equal([
26
26
  {id: 1, body: 'ZOMG A COMMENT'},
27
27
  {id: 2, body: 'ZOMG ANOTHER COMMENT'}
28
- ], @adapter.serializable_hash[:comments])
28
+ ], @adapter.serializable_hash[:post][:comments])
29
29
  end
30
30
  end
31
31
  end
@@ -31,7 +31,7 @@ module ActiveModel
31
31
 
32
32
  def test_create_adapter
33
33
  adapter = ActiveModel::Serializer::Adapter.create(@serializer)
34
- assert_equal ActiveModel::Serializer::Adapter::Json, adapter.class
34
+ assert_equal ActiveModel::Serializer::Adapter::FlattenJson, adapter.class
35
35
  end
36
36
 
37
37
  def test_create_adapter_with_override
@@ -24,6 +24,20 @@ module ActiveModel
24
24
 
25
25
  assert_equal serializers.last.custom_options[:some], :options
26
26
  end
27
+
28
+ def test_serializer_option_not_passed_to_each_serializer
29
+ serializers = ArraySerializer.new([@post], {serializer: PostSerializer}).to_a
30
+
31
+ refute serializers.first.custom_options.key?(:serializer)
32
+ end
33
+
34
+ def test_meta_and_meta_key_attr_readers
35
+ meta_content = {meta: "the meta", meta_key: "the meta key"}
36
+ @serializer = ArraySerializer.new([@comment, @post], meta_content)
37
+
38
+ assert_equal @serializer.meta, "the meta"
39
+ assert_equal @serializer.meta_key, "the meta key"
40
+ end
27
41
  end
28
42
  end
29
43
  end
@@ -1,4 +1,10 @@
1
1
  class Model
2
+ FILE_DIGEST = Digest::MD5.hexdigest(File.open(__FILE__).read)
3
+
4
+ def self.model_name
5
+ @_model_name ||= ActiveModel::Name.new(self)
6
+ end
7
+
2
8
  def initialize(hash={})
3
9
  @attributes = hash
4
10
  end
@@ -7,6 +13,10 @@ class Model
7
13
  "#{self.class.name.downcase}/#{self.id}-#{self.updated_at}"
8
14
  end
9
15
 
16
+ def cache_key_with_digest
17
+ "#{cache_key}/#{FILE_DIGEST}"
18
+ end
19
+
10
20
  def updated_at
11
21
  @attributes[:updated_at] ||= DateTime.now.to_time.to_i
12
22
  end
@@ -64,7 +74,7 @@ Author = Class.new(Model)
64
74
  Bio = Class.new(Model)
65
75
  Blog = Class.new(Model)
66
76
  Role = Class.new(Model)
67
- User = Class.new(Model)
77
+ User = Class.new(Model)
68
78
  Location = Class.new(Model)
69
79
  Place = Class.new(Model)
70
80
 
@@ -72,7 +82,7 @@ module Spam; end
72
82
  Spam::UnrelatedLink = Class.new(Model)
73
83
 
74
84
  PostSerializer = Class.new(ActiveModel::Serializer) do
75
- cache key:'post', expires_in: 0.1
85
+ cache key:'post', expires_in: 0.1, skip_digest: true
76
86
  attributes :id, :title, :body
77
87
 
78
88
  has_many :comments
@@ -99,7 +109,7 @@ SpammyPostSerializer = Class.new(ActiveModel::Serializer) do
99
109
  end
100
110
 
101
111
  CommentSerializer = Class.new(ActiveModel::Serializer) do
102
- cache expires_in: 1.day
112
+ cache expires_in: 1.day, skip_digest: true
103
113
  attributes :id, :body
104
114
 
105
115
  belongs_to :post
@@ -111,7 +121,7 @@ CommentSerializer = Class.new(ActiveModel::Serializer) do
111
121
  end
112
122
 
113
123
  AuthorSerializer = Class.new(ActiveModel::Serializer) do
114
- cache key:'writer'
124
+ cache key:'writer', skip_digest: true
115
125
  attributes :id, :name
116
126
 
117
127
  has_many :posts, embed: :ids
@@ -120,7 +130,7 @@ AuthorSerializer = Class.new(ActiveModel::Serializer) do
120
130
  end
121
131
 
122
132
  RoleSerializer = Class.new(ActiveModel::Serializer) do
123
- cache only: [:name]
133
+ cache only: [:name], skip_digest: true
124
134
  attributes :id, :name, :description, :slug
125
135
 
126
136
  def slug
@@ -137,7 +147,7 @@ LikeSerializer = Class.new(ActiveModel::Serializer) do
137
147
  end
138
148
 
139
149
  LocationSerializer = Class.new(ActiveModel::Serializer) do
140
- cache only: [:place]
150
+ cache only: [:place], skip_digest: true
141
151
  attributes :id, :lat, :lng
142
152
 
143
153
  belongs_to :place
@@ -154,13 +164,14 @@ PlaceSerializer = Class.new(ActiveModel::Serializer) do
154
164
  end
155
165
 
156
166
  BioSerializer = Class.new(ActiveModel::Serializer) do
157
- cache except: [:content]
167
+ cache except: [:content], skip_digest: true
158
168
  attributes :id, :content, :rating
159
169
 
160
170
  belongs_to :author
161
171
  end
162
172
 
163
173
  BlogSerializer = Class.new(ActiveModel::Serializer) do
174
+ cache key: 'blog'
164
175
  attributes :id, :name
165
176
 
166
177
  belongs_to :writer
@@ -178,6 +189,13 @@ AlternateBlogSerializer = Class.new(ActiveModel::Serializer) do
178
189
  attribute :name, key: :title
179
190
  end
180
191
 
192
+ CustomBlogSerializer = Class.new(ActiveModel::Serializer) do
193
+ attribute :id
194
+ attribute :special_attribute
195
+
196
+ has_many :articles
197
+ end
198
+
181
199
  CommentPreviewSerializer = Class.new(ActiveModel::Serializer) do
182
200
  attributes :id
183
201
 
@@ -204,3 +222,9 @@ end
204
222
  Spam::UnrelatedLinkSerializer = Class.new(ActiveModel::Serializer) do
205
223
  attributes :id
206
224
  end
225
+
226
+ RaiseErrorSerializer = Class.new(ActiveModel::Serializer) do
227
+ def json_key
228
+ raise StandardError, 'Intentional error for rescue_from test'
229
+ end
230
+ end
@@ -0,0 +1,24 @@
1
+ require 'test_helper'
2
+ # require 'active_model/serializer/railtie'
3
+
4
+ class ResourceGeneratorTest < Rails::Generators::TestCase
5
+ destination File.expand_path('../../../tmp/generators', __FILE__)
6
+ setup :prepare_destination, :copy_routes
7
+
8
+ tests Rails::Generators::ResourceGenerator
9
+ arguments %w(account)
10
+
11
+ def test_serializer_file_is_generated
12
+ run_generator
13
+
14
+ assert_file 'app/serializers/account_serializer.rb', /class AccountSerializer < ActiveModel::Serializer/
15
+ end
16
+
17
+ private
18
+
19
+ def copy_routes
20
+ config_dir = File.join(destination_root, 'config')
21
+ FileUtils.mkdir_p(config_dir)
22
+ File.write(File.join(config_dir, 'routes.rb'), 'Rails.application.routes.draw { }')
23
+ end
24
+ end