active_model_serializers 0.9.0 → 0.9.3

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 (34) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/README.md +109 -17
  4. data/lib/action_controller/serialization.rb +27 -8
  5. data/lib/action_controller/serialization_test_case.rb +4 -4
  6. data/lib/active_model/array_serializer.rb +12 -5
  7. data/lib/active_model/serializable.rb +24 -2
  8. data/lib/active_model/serializable/utils.rb +16 -0
  9. data/lib/active_model/serializer.rb +70 -36
  10. data/lib/active_model/serializer/{associations.rb → association.rb} +8 -52
  11. data/lib/active_model/serializer/association/has_many.rb +39 -0
  12. data/lib/active_model/serializer/association/has_one.rb +25 -0
  13. data/lib/active_model/serializer/railtie.rb +8 -0
  14. data/lib/active_model/serializer/version.rb +1 -1
  15. data/lib/active_model_serializers.rb +1 -1
  16. data/test/fixtures/poro.rb +106 -1
  17. data/test/fixtures/template.html.erb +1 -0
  18. data/test/integration/action_controller/namespaced_serialization_test.rb +96 -0
  19. data/test/integration/action_controller/serialization_test_case_test.rb +10 -0
  20. data/test/integration/active_record/active_record_test.rb +2 -2
  21. data/test/serializers/tmp/app/serializers/account_serializer.rb +3 -0
  22. data/test/test_app.rb +3 -0
  23. data/test/unit/active_model/array_serializer/serialization_test.rb +1 -1
  24. data/test/unit/active_model/serializer/associations/build_serializer_test.rb +15 -0
  25. data/test/unit/active_model/serializer/attributes_test.rb +16 -0
  26. data/test/unit/active_model/serializer/config_test.rb +3 -0
  27. data/test/unit/active_model/serializer/has_many_polymorphic_test.rb +189 -0
  28. data/test/unit/active_model/serializer/has_many_test.rb +51 -16
  29. data/test/unit/active_model/serializer/has_one_and_has_many_test.rb +27 -0
  30. data/test/unit/active_model/serializer/has_one_polymorphic_test.rb +196 -0
  31. data/test/unit/active_model/serializer/has_one_test.rb +32 -0
  32. data/test/unit/active_model/serializer/options_test.rb +19 -0
  33. data/test/unit/active_model/serializer/url_helpers_test.rb +35 -0
  34. metadata +44 -27
@@ -11,6 +11,11 @@ module ActionController
11
11
  def render_text
12
12
  render text: 'ok'
13
13
  end
14
+
15
+ def render_template
16
+ prepend_view_path "./test/fixtures"
17
+ render template: "template"
18
+ end
14
19
  end
15
20
 
16
21
  tests MyController
@@ -56,6 +61,11 @@ module ActionController
56
61
  end
57
62
  assert_match 'assert_serializer only accepts a String, Symbol, Regexp, ActiveModel::Serializer, or nil', e.message
58
63
  end
64
+
65
+ def test_does_not_overwrite_notification_subscriptions
66
+ get :render_template
67
+ assert_template "template"
68
+ end
59
69
  end
60
70
  end
61
71
  end
@@ -49,9 +49,9 @@ module ActiveModel
49
49
  'ar_tag_ids' => [1, 2],
50
50
  'ar_section_id' => 1
51
51
  },
52
- ar_comments: [{ body: 'what a dumb post', 'ar_tag_ids' => [3, 2] },
52
+ 'ar_comments' => [{ body: 'what a dumb post', 'ar_tag_ids' => [3, 2] },
53
53
  { body: 'i liked it', 'ar_tag_ids' => [3, 1] }],
54
- ar_tags: [{ name: 'happy' }, { name: 'whiny' }, { name: 'short' }],
54
+ 'ar_tags' => [{ name: 'happy' }, { name: 'whiny' }, { name: 'short' }],
55
55
  'ar_sections' => [{ 'name' => 'ruby' }]
56
56
  }, post_serializer.as_json)
57
57
  end
@@ -0,0 +1,3 @@
1
+ class AccountSerializer < ActiveModel::Serializer
2
+ attributes :id
3
+ end
data/test/test_app.rb CHANGED
@@ -3,6 +3,9 @@ class TestApp < Rails::Application
3
3
  config.eager_load = false
4
4
  config.secret_key_base = 'abc123'
5
5
  end
6
+ config.after_initialize do
7
+ Rails.application.routes.default_url_options = { host: 'http://example.com' }
8
+ end
6
9
 
7
10
  # Set up a logger to avoid creating a log directory on every run.
8
11
  config.logger = Logger.new(nil)
@@ -85,7 +85,7 @@ module ActiveModel
85
85
  {title: "Title 1", body: "Body 1", "comment_ids" => @post1.comments.map(&:object_id) },
86
86
  {title: "Title 2", body: "Body 2", "comment_ids" => @post2.comments.map(&:object_id) }
87
87
  ],
88
- comments: [
88
+ 'comments' => [
89
89
  {content: "C1"},
90
90
  {content: "C2"},
91
91
  {content: "C3"},
@@ -7,6 +7,7 @@ module ActiveModel
7
7
  def setup
8
8
  @association = Association::HasOne.new('post', serializer: PostSerializer)
9
9
  @post = Post.new({ title: 'Title 1', body: 'Body 1', date: '1/1/2000' })
10
+ @user = User.new
10
11
  end
11
12
 
12
13
  def test_build_serializer_for_array_called_twice
@@ -15,6 +16,20 @@ module ActiveModel
15
16
  assert_instance_of(PostSerializer, serializer)
16
17
  end
17
18
  end
19
+
20
+ def test_build_serializer_from_in_a_namespace
21
+ assoc = Association::HasOne.new('profile')
22
+ serializer = TestNamespace::UserSerializer.new(@user).build_serializer(assoc)
23
+
24
+ assert_instance_of(TestNamespace::ProfileSerializer, serializer)
25
+ end
26
+
27
+ def test_build_serializer_with_prefix
28
+ assoc = Association::HasOne.new('profile', prefix: :short)
29
+ serializer = UserSerializer.new(@user).build_serializer(assoc)
30
+
31
+ assert_instance_of(ShortProfileSerializer, serializer)
32
+ end
18
33
  end
19
34
  end
20
35
  end
@@ -36,6 +36,22 @@ module ActiveModel
36
36
  assert_equal([:name, :description],
37
37
  another_inherited_serializer_klass._attributes)
38
38
  end
39
+
40
+ def tests_query_attributes_strip_question_mark
41
+ model = Class.new(::Model) do
42
+ def strip?
43
+ true
44
+ end
45
+ end
46
+
47
+ serializer = Class.new(ActiveModel::Serializer) do
48
+ attributes :strip?
49
+ end
50
+
51
+ actual = serializer.new(model.new).as_json
52
+
53
+ assert_equal({ strip: true }, actual)
54
+ end
39
55
  end
40
56
  end
41
57
  end
@@ -78,6 +78,9 @@ module ActiveModel
78
78
  assert !association.embed_objects?
79
79
  assert association.embed_in_root
80
80
  assert_equal :lower_camel, association.key_format
81
+ assert_equal 'post', PostSerializer.root_name
82
+ CONFIG.plural_default_root = true
83
+ assert_equal 'posts', PostSerializer.root_name
81
84
  ensure
82
85
  PostSerializer._associations[:comments] = old_association
83
86
  CONFIG.clear
@@ -0,0 +1,189 @@
1
+ require 'test_helper'
2
+
3
+ module ActiveModel
4
+ class Serializer
5
+ class HasManyPolymorphicTest < ActiveModel::TestCase
6
+ def setup
7
+ @association = MailSerializer._associations[:attachments]
8
+ @old_association = @association.dup
9
+
10
+ @mail = Mail.new({ body: 'Body 1' })
11
+ @mail_serializer = MailSerializer.new(@mail)
12
+ end
13
+
14
+ def teardown
15
+ MailSerializer._associations[:attachments] = @old_association
16
+ end
17
+
18
+ def model_name(object)
19
+ object.class.to_s.demodulize.underscore.to_sym
20
+ end
21
+
22
+ def test_associations_definition
23
+ assert_equal 1, MailSerializer._associations.length
24
+ assert_kind_of Association::HasMany, @association
25
+ assert_equal true, @association.polymorphic
26
+ assert_equal 'attachments', @association.name
27
+ end
28
+
29
+ def test_associations_embedding_ids_serialization_using_serializable_hash
30
+ @association.embed = :ids
31
+
32
+ assert_equal({
33
+ body: 'Body 1',
34
+ 'attachment_ids' => @mail.attachments.map do |c|
35
+ { id: c.object_id, type: model_name(c) }
36
+ end
37
+ }, @mail_serializer.serializable_hash)
38
+ end
39
+
40
+ def test_associations_embedding_ids_serialization_using_as_json
41
+ @association.embed = :ids
42
+
43
+ assert_equal({
44
+ 'mail' => {
45
+ :body => 'Body 1',
46
+ 'attachment_ids' => @mail.attachments.map do |c|
47
+ { id: c.object_id, type: model_name(c) }
48
+ end
49
+ }
50
+ }, @mail_serializer.as_json)
51
+ end
52
+
53
+ def test_associations_embedding_ids_serialization_using_serializable_hash_and_key_from_options
54
+ @association.embed = :ids
55
+ @association.key = 'key'
56
+
57
+ assert_equal({
58
+ body: 'Body 1',
59
+ 'key' => @mail.attachments.map do |c|
60
+ { id: c.object_id, type: model_name(c) }
61
+ end
62
+ }, @mail_serializer.serializable_hash)
63
+ end
64
+
65
+ def test_associations_embedding_objects_serialization_using_serializable_hash
66
+ @association.embed = :objects
67
+
68
+ assert_equal({
69
+ body: 'Body 1',
70
+ :attachments => [
71
+ { type: :image, image: { url: 'U1' }},
72
+ { type: :video, video: { html: 'H1' }}
73
+ ]
74
+ }, @mail_serializer.serializable_hash)
75
+ end
76
+
77
+ def test_associations_embedding_objects_serialization_using_as_json
78
+ @association.embed = :objects
79
+
80
+ assert_equal({
81
+ 'mail' => {
82
+ body: 'Body 1',
83
+ attachments: [
84
+ { type: :image, image: { url: 'U1' }},
85
+ { type: :video, video: { html: 'H1' }}
86
+ ]
87
+ }
88
+ }, @mail_serializer.as_json)
89
+ end
90
+
91
+ def test_associations_embedding_nil_objects_serialization_using_as_json
92
+ @association.embed = :objects
93
+ @mail.instance_eval do
94
+ def attachments
95
+ [nil]
96
+ end
97
+ end
98
+
99
+ assert_equal({
100
+ 'mail' => {
101
+ :body => 'Body 1',
102
+ :attachments => [nil]
103
+ }
104
+ }, @mail_serializer.as_json)
105
+ end
106
+
107
+ def test_associations_embedding_objects_serialization_using_serializable_hash_and_root_from_options
108
+ @association.embed = :objects
109
+ @association.embedded_key = 'root'
110
+
111
+ assert_equal({
112
+ body: 'Body 1',
113
+ 'root' => [
114
+ { type: :image, image: { url: 'U1' }},
115
+ { type: :video, video: { html: 'H1' }}
116
+ ]
117
+ }, @mail_serializer.serializable_hash)
118
+ end
119
+
120
+ def test_associations_embedding_ids_including_objects_serialization_using_serializable_hash
121
+ @association.embed = :ids
122
+ @association.embed_in_root = true
123
+
124
+ assert_equal({
125
+ body: 'Body 1',
126
+ 'attachment_ids' => @mail.attachments.map do |c|
127
+ { id: c.object_id, type: model_name(c) }
128
+ end
129
+ }, @mail_serializer.serializable_hash)
130
+ end
131
+
132
+ def test_associations_embedding_ids_including_objects_serialization_using_as_json
133
+ @association.embed = :ids
134
+ @association.embed_in_root = true
135
+
136
+ assert_equal({
137
+ 'mail' => {
138
+ body: 'Body 1',
139
+ 'attachment_ids' => @mail.attachments.map do |c|
140
+ { id: c.object_id, type: model_name(c) }
141
+ end,
142
+ },
143
+ 'attachments' => [
144
+ { type: :image, image: { url: 'U1' }},
145
+ { type: :video, video: { html: 'H1' }}
146
+ ]
147
+ }, @mail_serializer.as_json)
148
+ end
149
+
150
+ def test_associations_embedding_nothing_including_objects_serialization_using_as_json
151
+ @association.embed = nil
152
+ @association.embed_in_root = true
153
+
154
+ assert_equal({
155
+ 'mail' => { body: 'Body 1' },
156
+ 'attachments' => [
157
+ { type: :image, image: { url: 'U1' }},
158
+ { type: :video, video: { html: 'H1' }}
159
+ ]
160
+ }, @mail_serializer.as_json)
161
+ end
162
+
163
+ def test_associations_using_a_given_serializer
164
+ @association.embed = :ids
165
+ @association.embed_in_root = true
166
+ @association.serializer_from_options = Class.new(ActiveModel::Serializer) do
167
+ def fake
168
+ 'fake'
169
+ end
170
+
171
+ attributes :fake
172
+ end
173
+
174
+ assert_equal({
175
+ 'mail' => {
176
+ body: 'Body 1',
177
+ 'attachment_ids' => @mail.attachments.map do |c|
178
+ { id: c.object_id, type: model_name(c) }
179
+ end
180
+ },
181
+ 'attachments' => [
182
+ { type: :image, image: { fake: 'fake' }},
183
+ { type: :video, video: { fake: 'fake' }}
184
+ ]
185
+ }, @mail_serializer.as_json)
186
+ end
187
+ end
188
+ end
189
+ end
@@ -111,17 +111,34 @@ module ActiveModel
111
111
 
112
112
  assert_equal({
113
113
  'post' => { title: 'Title 1', body: 'Body 1', 'comment_ids' => @post.comments.map { |c| c.object_id } },
114
- comments: [{ content: 'C1' }, { content: 'C2' }]
114
+ 'comments' => [{ content: 'C1' }, { content: 'C2' }]
115
115
  }, @post_serializer.as_json)
116
116
  end
117
117
 
118
+ def test_associations_embedding_ids_including_objects_serialization_when_invoked_from_parent_serializer
119
+ @association.embed = :ids
120
+ @association.embed_in_root = true
121
+
122
+ category = Category.new(name: 'Name 1')
123
+ category.instance_variable_set(:@posts, [@post])
124
+ category_serializer = CategorySerializer.new(category)
125
+
126
+ assert_equal({
127
+ 'category' => {
128
+ name: 'Name 1',
129
+ posts: [{ title: 'Title 1', body: 'Body 1', 'comment_ids' => @post.comments.map { |c| c.object_id } }]
130
+ },
131
+ "comments" => [{ content: 'C1' }, { content: 'C2' }]
132
+ }, category_serializer.as_json)
133
+ end
134
+
118
135
  def test_associations_embedding_nothing_including_objects_serialization_using_as_json
119
136
  @association.embed = nil
120
137
  @association.embed_in_root = true
121
138
 
122
139
  assert_equal({
123
140
  'post' => { title: 'Title 1', body: 'Body 1' },
124
- comments: [{ content: 'C1' }, { content: 'C2' }]
141
+ 'comments' => [{ content: 'C1' }, { content: 'C2' }]
125
142
  }, @post_serializer.as_json)
126
143
  end
127
144
 
@@ -138,7 +155,7 @@ module ActiveModel
138
155
 
139
156
  assert_equal({
140
157
  'post' => { title: 'Title 1', body: 'Body 1', 'comment_ids' => @post.comments.map { |c| c.object_id } },
141
- comments: [{ content: 'C1!' }, { content: 'C2!' }]
158
+ 'comments' => [{ content: 'C1!' }, { content: 'C2!' }]
142
159
  }, @post_serializer.as_json)
143
160
  end
144
161
 
@@ -153,7 +170,7 @@ module ActiveModel
153
170
 
154
171
  assert_equal({
155
172
  'post' => { title: 'Title 1', body: 'Body 1', 'comment_ids' => @post.comments.map { |c| c.object_id } },
156
- comments: { my_content: ['fake'] }
173
+ 'comments' => { my_content: ['fake'] }
157
174
  }, @post_serializer.as_json)
158
175
  end
159
176
 
@@ -174,16 +191,16 @@ module ActiveModel
174
191
  @association.embed_in_root_key = :linked
175
192
  @association.embed = :ids
176
193
  assert_equal({
194
+ 'post' => {
195
+ title: 'Title 1', body: 'Body 1',
196
+ 'comment_ids' => @post.comments.map(&:object_id)
197
+ },
177
198
  linked: {
178
- comments: [
199
+ 'comments' => [
179
200
  { content: 'C1' },
180
201
  { content: 'C2' }
181
202
  ]
182
203
  },
183
- 'post' => {
184
- title: 'Title 1', body: 'Body 1',
185
- 'comment_ids' => @post.comments.map(&:object_id)
186
- }
187
204
  }, @post_serializer.as_json)
188
205
  end
189
206
 
@@ -194,18 +211,18 @@ module ActiveModel
194
211
  @association.embed_namespace = :links
195
212
  @association.key = :comments
196
213
  assert_equal({
197
- linked: {
198
- comments: [
199
- { content: 'C1' },
200
- { content: 'C2' }
201
- ]
202
- },
203
214
  'post' => {
204
215
  title: 'Title 1', body: 'Body 1',
205
216
  links: {
206
217
  comments: @post.comments.map(&:object_id)
207
218
  }
208
- }
219
+ },
220
+ linked: {
221
+ 'comments' => [
222
+ { content: 'C1' },
223
+ { content: 'C2' }
224
+ ]
225
+ },
209
226
  }, @post_serializer.as_json)
210
227
  end
211
228
 
@@ -225,6 +242,24 @@ module ActiveModel
225
242
  }
226
243
  }, @post_serializer.as_json)
227
244
  end
245
+
246
+ def test_associations_name_key_embedding_ids_serialization_using_serializable_hash
247
+ @association = NameKeyPostSerializer._associations[:comments]
248
+ @association.embed = :ids
249
+
250
+ assert_equal({
251
+ title: 'Title 1', body: 'Body 1', 'comments' => @post.comments.map { |c| c.object_id }
252
+ }, NameKeyPostSerializer.new(@post).serializable_hash)
253
+ end
254
+
255
+ def test_associations_name_key_embedding_ids_serialization_using_as_json
256
+ @association = NameKeyPostSerializer._associations[:comments]
257
+ @association.embed = :ids
258
+
259
+ assert_equal({
260
+ 'name_key_post' => { title: 'Title 1', body: 'Body 1', 'comments' => @post.comments.map { |c| c.object_id } }
261
+ }, NameKeyPostSerializer.new(@post).as_json)
262
+ end
228
263
  end
229
264
  end
230
265
  end
@@ -0,0 +1,27 @@
1
+ require 'test_helper'
2
+
3
+ module ActiveModel
4
+ class Serializer
5
+ class HasOneAndHasManyTest < Minitest::Test
6
+ def setup
7
+ @post = SpecialPost.new({ title: 'T1', body: 'B1'})
8
+ @post_serializer = SpecialPostSerializer.new(@post)
9
+ end
10
+
11
+ def teardown
12
+ end
13
+
14
+ def test_side_load_has_one_and_has_many_in_same_array
15
+ assert_equal({
16
+ "post" => {
17
+ title: 'T1',
18
+ body: 'B1',
19
+ 'comment_ids' => @post.comments.map { |c| c.object_id },
20
+ 'special_comment_id' => @post_serializer.special_comment.object_id,
21
+ },
22
+ "comments" => [{ content: 'C1' }, { content: 'C2' }, { content: 'special' }]
23
+ }, @post_serializer.as_json(root: 'post'))
24
+ end
25
+ end
26
+ end
27
+ end