active_model_serializers 0.10.0.rc5 → 0.10.0
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.
- checksums.yaml +4 -4
- data/.gitignore +10 -0
- data/.travis.yml +0 -8
- data/CHANGELOG.md +23 -0
- data/CONTRIBUTING.md +14 -4
- data/Gemfile +1 -2
- data/README.md +3 -3
- data/active_model_serializers.gemspec +1 -1
- data/appveyor.yml +6 -10
- data/docs/ARCHITECTURE.md +1 -1
- data/docs/README.md +1 -0
- data/docs/general/deserialization.md +19 -19
- data/docs/general/serializers.md +33 -0
- data/docs/howto/serialize_poro.md +32 -0
- data/lib/active_model/serializer.rb +2 -0
- data/lib/active_model/serializer/caching.rb +185 -3
- data/lib/active_model/serializer/field.rb +36 -2
- data/lib/active_model/serializer/lint.rb +8 -18
- data/lib/active_model/serializer/version.rb +1 -1
- data/lib/active_model_serializers.rb +0 -2
- data/lib/active_model_serializers/adapter/attributes.rb +20 -38
- data/lib/active_model_serializers/adapter/base.rb +8 -15
- data/lib/active_model_serializers/adapter/json.rb +12 -2
- data/lib/active_model_serializers/adapter/json_api.rb +33 -30
- data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +10 -5
- data/lib/active_model_serializers/adapter/null.rb +1 -2
- data/lib/active_model_serializers/register_jsonapi_renderer.rb +3 -2
- data/lib/active_model_serializers/serializable_resource.rb +1 -1
- data/lib/active_model_serializers/test/schema.rb +44 -9
- data/test/action_controller/json_api/transform_test.rb +2 -1
- data/test/action_controller/serialization_test.rb +3 -1
- data/test/active_model_serializers/test/schema_test.rb +5 -3
- data/test/active_model_serializers/test/serializer_test.rb +1 -2
- data/test/adapter/json/transform_test.rb +14 -14
- data/test/adapter/json_api/has_many_test.rb +3 -2
- data/test/adapter/json_api/has_one_test.rb +3 -2
- data/test/adapter/json_api/pagination_links_test.rb +39 -21
- data/test/adapter/json_api/transform_test.rb +36 -34
- data/test/adapter/polymorphic_test.rb +111 -12
- data/test/adapter_test.rb +27 -0
- data/test/array_serializer_test.rb +10 -25
- data/test/benchmark/bm_caching.rb +17 -15
- data/test/benchmark/controllers.rb +9 -2
- data/test/benchmark/fixtures.rb +56 -4
- data/test/cache_test.rb +103 -6
- data/test/fixtures/active_record.rb +10 -0
- data/test/fixtures/poro.rb +31 -3
- data/test/serializers/associations_test.rb +43 -15
- data/test/serializers/attribute_test.rb +44 -16
- data/test/serializers/meta_test.rb +5 -7
- data/test/support/isolated_unit.rb +0 -1
- data/test/test_helper.rb +19 -21
- metadata +7 -12
- data/lib/active_model_serializers/cached_serializer.rb +0 -87
- data/lib/active_model_serializers/fragment_cache.rb +0 -118
- data/test/active_model_serializers/cached_serializer_test.rb +0 -80
- data/test/active_model_serializers/fragment_cache_test.rb +0 -34
@@ -1,12 +1,13 @@
|
|
1
1
|
class PostController < ActionController::Base
|
2
2
|
POST =
|
3
3
|
begin
|
4
|
+
updated_at = Time.current
|
4
5
|
if ENV['BENCH_STRESS']
|
5
6
|
comments = (0..50).map do |i|
|
6
|
-
Comment.new(id: i, body: 'ZOMG A COMMENT')
|
7
|
+
Comment.new(id: i, body: 'ZOMG A COMMENT', updated_at: updated_at + i)
|
7
8
|
end
|
8
9
|
else
|
9
|
-
comments = [Comment.new(id: 1, body: 'ZOMG A COMMENT')]
|
10
|
+
comments = [Comment.new(id: 1, body: 'ZOMG A COMMENT', updated_at: updated_at)]
|
10
11
|
end
|
11
12
|
author = Author.new(id: 42, first_name: 'Joao', last_name: 'Moura')
|
12
13
|
Post.new(id: 1337, title: 'New Post', blog: nil, body: 'Body', comments: comments, author: author)
|
@@ -17,6 +18,11 @@ class PostController < ActionController::Base
|
|
17
18
|
render json: POST, serializer: CachingPostSerializer, adapter: :json, meta: { caching: perform_caching }
|
18
19
|
end
|
19
20
|
|
21
|
+
def render_with_fragment_caching_serializer
|
22
|
+
toggle_cache_status
|
23
|
+
render json: POST, serializer: FragmentCachingPostSerializer, adapter: :json, meta: { caching: perform_caching }
|
24
|
+
end
|
25
|
+
|
20
26
|
def render_with_non_caching_serializer
|
21
27
|
toggle_cache_status
|
22
28
|
render json: POST, adapter: :json, meta: { caching: perform_caching }
|
@@ -73,5 +79,6 @@ Rails.application.routes.draw do
|
|
73
79
|
get '/status(/:on)' => 'post#render_cache_status'
|
74
80
|
get '/clear' => 'post#clear'
|
75
81
|
get '/caching(/:on)' => 'post#render_with_caching_serializer'
|
82
|
+
get '/fragment_caching(/:on)' => 'post#render_with_fragment_caching_serializer'
|
76
83
|
get '/non_caching(/:on)' => 'post#render_with_non_caching_serializer'
|
77
84
|
end
|
data/test/benchmark/fixtures.rb
CHANGED
@@ -13,7 +13,7 @@ end
|
|
13
13
|
Rails.configuration.serializers << BlogSerializer
|
14
14
|
|
15
15
|
class CommentSerializer < ActiveModel::Serializer
|
16
|
-
attributes :id, :body
|
16
|
+
attributes :id, :body, :updated_at
|
17
17
|
|
18
18
|
belongs_to :post
|
19
19
|
belongs_to :author
|
@@ -43,7 +43,7 @@ end
|
|
43
43
|
Rails.configuration.serializers << PostSerializer
|
44
44
|
|
45
45
|
class CachingAuthorSerializer < AuthorSerializer
|
46
|
-
cache key: 'writer',
|
46
|
+
cache key: 'writer', skip_digest: true
|
47
47
|
end
|
48
48
|
Rails.configuration.serializers << CachingAuthorSerializer
|
49
49
|
|
@@ -52,14 +52,66 @@ class CachingCommentSerializer < CommentSerializer
|
|
52
52
|
end
|
53
53
|
Rails.configuration.serializers << CachingCommentSerializer
|
54
54
|
|
55
|
-
|
55
|
+
# see https://github.com/rails-api/active_model_serializers/pull/1690/commits/68715b8f99bc29677e8a47bb3f305f23c077024b#r60344532
|
56
|
+
class CachingPostSerializer < ActiveModel::Serializer
|
56
57
|
cache key: 'post', expires_in: 0.1, skip_digest: true
|
58
|
+
|
59
|
+
attributes :id, :title, :body
|
60
|
+
|
57
61
|
belongs_to :blog, serializer: BlogSerializer
|
58
62
|
belongs_to :author, serializer: CachingAuthorSerializer
|
59
63
|
has_many :comments, serializer: CachingCommentSerializer
|
64
|
+
|
65
|
+
link(:post_authors) { 'https://example.com/post_authors' }
|
66
|
+
|
67
|
+
meta do
|
68
|
+
{
|
69
|
+
rating: 5,
|
70
|
+
favorite_count: 10
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
def blog
|
75
|
+
Blog.new(id: 999, name: 'Custom blog')
|
76
|
+
end
|
60
77
|
end
|
61
78
|
Rails.configuration.serializers << CachingPostSerializer
|
62
79
|
|
80
|
+
class FragmentCachingAuthorSerializer < AuthorSerializer
|
81
|
+
cache key: 'writer', only: [:first_name, :last_name], skip_digest: true
|
82
|
+
end
|
83
|
+
Rails.configuration.serializers << FragmentCachingAuthorSerializer
|
84
|
+
|
85
|
+
class FragmentCachingCommentSerializer < CommentSerializer
|
86
|
+
cache expires_in: 1.day, except: [:updated_at], skip_digest: true
|
87
|
+
end
|
88
|
+
Rails.configuration.serializers << CachingCommentSerializer
|
89
|
+
|
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
|
93
|
+
|
94
|
+
attributes :id, :title, :body
|
95
|
+
|
96
|
+
belongs_to :blog, serializer: BlogSerializer
|
97
|
+
belongs_to :author, serializer: FragmentCachingAuthorSerializer
|
98
|
+
has_many :comments, serializer: FragmentCachingCommentSerializer
|
99
|
+
|
100
|
+
link(:post_authors) { 'https://example.com/post_authors' }
|
101
|
+
|
102
|
+
meta do
|
103
|
+
{
|
104
|
+
rating: 5,
|
105
|
+
favorite_count: 10
|
106
|
+
}
|
107
|
+
end
|
108
|
+
|
109
|
+
def blog
|
110
|
+
Blog.new(id: 999, name: 'Custom blog')
|
111
|
+
end
|
112
|
+
end
|
113
|
+
Rails.configuration.serializers << FragmentCachingPostSerializer
|
114
|
+
|
63
115
|
if ENV['ENABLE_ACTIVE_RECORD'] == 'true'
|
64
116
|
require 'active_record'
|
65
117
|
|
@@ -150,7 +202,7 @@ else
|
|
150
202
|
end
|
151
203
|
|
152
204
|
class Comment < BenchmarkModel
|
153
|
-
attr_accessor :id, :body
|
205
|
+
attr_accessor :id, :body, :updated_at
|
154
206
|
end
|
155
207
|
|
156
208
|
class Author < BenchmarkModel
|
data/test/cache_test.rb
CHANGED
@@ -114,7 +114,7 @@ module ActiveModelSerializers
|
|
114
114
|
|
115
115
|
def test_error_is_raised_if_cache_key_is_not_defined_on_object_or_passed_as_cache_option
|
116
116
|
article = Article.new(title: 'Must Read')
|
117
|
-
e = assert_raises
|
117
|
+
e = assert_raises ActiveModel::Serializer::UndefinedCacheKey do
|
118
118
|
render_object_with_cache(article)
|
119
119
|
end
|
120
120
|
assert_match(/ActiveModelSerializers::CacheTest::Article must define #cache_key, or the 'key:' option must be passed into 'CachedActiveModelSerializers_CacheTest_ArticleSerializer.cache'/, e.message)
|
@@ -252,11 +252,11 @@ module ActiveModelSerializers
|
|
252
252
|
attributes_serialization = serializable_alert.as_json
|
253
253
|
assert_equal expected_cached_attributes, alert.attributes
|
254
254
|
assert_equal alert.attributes, attributes_serialization
|
255
|
-
attributes_cache_key =
|
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)
|
257
257
|
|
258
258
|
serializable_alert = serializable(alert, serializer: AlertSerializer, adapter: :json_api)
|
259
|
-
jsonapi_cache_key =
|
259
|
+
jsonapi_cache_key = serializable_alert.adapter.serializer.cache_key(serializable_alert.adapter)
|
260
260
|
# Assert cache keys differ
|
261
261
|
refute_equal attributes_cache_key, jsonapi_cache_key
|
262
262
|
# Assert (cached) serializations differ
|
@@ -288,9 +288,9 @@ module ActiveModelSerializers
|
|
288
288
|
serializable = ActiveModelSerializers::SerializableResource.new([@comment, @comment])
|
289
289
|
include_tree = ActiveModel::Serializer::IncludeTree.from_include_args('*')
|
290
290
|
|
291
|
-
actual =
|
291
|
+
actual = ActiveModel::Serializer.object_cache_keys(serializable.adapter.serializer, serializable.adapter, include_tree)
|
292
292
|
|
293
|
-
assert_equal actual.size
|
293
|
+
assert_equal 3, actual.size
|
294
294
|
assert actual.any? { |key| key == "comment/1/#{serializable.adapter.cached_name}" }
|
295
295
|
assert actual.any? { |key| key =~ %r{post/post-\d+} }
|
296
296
|
assert actual.any? { |key| key =~ %r{author/author-\d+} }
|
@@ -365,12 +365,109 @@ module ActiveModelSerializers
|
|
365
365
|
assert called
|
366
366
|
end
|
367
367
|
|
368
|
+
def test_cached_false_without_cache_store
|
369
|
+
cached_serializer = build_cached_serializer do |serializer|
|
370
|
+
serializer._cache = nil
|
371
|
+
end
|
372
|
+
refute cached_serializer.class.cache_enabled?
|
373
|
+
end
|
374
|
+
|
375
|
+
def test_cached_true_with_cache_store_and_without_cache_only_and_cache_except
|
376
|
+
cached_serializer = build_cached_serializer do |serializer|
|
377
|
+
serializer._cache = Object
|
378
|
+
end
|
379
|
+
assert cached_serializer.class.cache_enabled?
|
380
|
+
end
|
381
|
+
|
382
|
+
def test_cached_false_with_cache_store_and_with_cache_only
|
383
|
+
cached_serializer = build_cached_serializer do |serializer|
|
384
|
+
serializer._cache = Object
|
385
|
+
serializer._cache_only = [:name]
|
386
|
+
end
|
387
|
+
refute cached_serializer.class.cache_enabled?
|
388
|
+
end
|
389
|
+
|
390
|
+
def test_cached_false_with_cache_store_and_with_cache_except
|
391
|
+
cached_serializer = build_cached_serializer do |serializer|
|
392
|
+
serializer._cache = Object
|
393
|
+
serializer._cache_except = [:content]
|
394
|
+
end
|
395
|
+
refute cached_serializer.class.cache_enabled?
|
396
|
+
end
|
397
|
+
|
398
|
+
def test_fragment_cached_false_without_cache_store
|
399
|
+
cached_serializer = build_cached_serializer do |serializer|
|
400
|
+
serializer._cache = nil
|
401
|
+
serializer._cache_only = [:name]
|
402
|
+
end
|
403
|
+
refute cached_serializer.class.fragment_cache_enabled?
|
404
|
+
end
|
405
|
+
|
406
|
+
def test_fragment_cached_true_with_cache_store_and_cache_only
|
407
|
+
cached_serializer = build_cached_serializer do |serializer|
|
408
|
+
serializer._cache = Object
|
409
|
+
serializer._cache_only = [:name]
|
410
|
+
end
|
411
|
+
assert cached_serializer.class.fragment_cache_enabled?
|
412
|
+
end
|
413
|
+
|
414
|
+
def test_fragment_cached_true_with_cache_store_and_cache_except
|
415
|
+
cached_serializer = build_cached_serializer do |serializer|
|
416
|
+
serializer._cache = Object
|
417
|
+
serializer._cache_except = [:content]
|
418
|
+
end
|
419
|
+
assert cached_serializer.class.fragment_cache_enabled?
|
420
|
+
end
|
421
|
+
|
422
|
+
def test_fragment_cached_false_with_cache_store_and_cache_except_and_cache_only
|
423
|
+
cached_serializer = build_cached_serializer do |serializer|
|
424
|
+
serializer._cache = Object
|
425
|
+
serializer._cache_except = [:content]
|
426
|
+
serializer._cache_only = [:name]
|
427
|
+
end
|
428
|
+
refute cached_serializer.class.fragment_cache_enabled?
|
429
|
+
end
|
430
|
+
|
431
|
+
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
|
+
|
438
|
+
expected_result = {
|
439
|
+
id: @role.id,
|
440
|
+
description: @role.description,
|
441
|
+
slug: "#{@role.name}-#{@role.id}",
|
442
|
+
name: @role.name
|
443
|
+
}
|
444
|
+
assert_equal(@role_hash, expected_result)
|
445
|
+
end
|
446
|
+
|
447
|
+
def test_fragment_fetch_with_namespaced_object
|
448
|
+
@spam = Spam::UnrelatedLink.new(id: 'spam-id-1')
|
449
|
+
@spam_serializer = Spam::UnrelatedLinkSerializer.new(@spam)
|
450
|
+
@spam_hash = @spam_serializer.fetch_fragment_cache(ActiveModelSerializers::Adapter.configured_adapter.new(@spam_serializer))
|
451
|
+
expected_result = {
|
452
|
+
id: @spam.id
|
453
|
+
}
|
454
|
+
assert_equal(@spam_hash, expected_result)
|
455
|
+
end
|
456
|
+
|
368
457
|
private
|
369
458
|
|
370
459
|
def cache_store
|
371
460
|
ActiveModelSerializers.config.cache_store
|
372
461
|
end
|
373
462
|
|
463
|
+
def build_cached_serializer
|
464
|
+
serializer = Class.new(ActiveModel::Serializer)
|
465
|
+
serializer._cache_key = nil
|
466
|
+
serializer._cache_options = nil
|
467
|
+
yield serializer if block_given?
|
468
|
+
serializer.new(Object)
|
469
|
+
end
|
470
|
+
|
374
471
|
def render_object_with_cache(obj, options = {})
|
375
472
|
@serializable_resource = serializable(obj, options)
|
376
473
|
@serializable_resource.serializable_hash
|
@@ -381,7 +478,7 @@ module ActiveModelSerializers
|
|
381
478
|
end
|
382
479
|
|
383
480
|
def cached_serialization(serializer)
|
384
|
-
cache_key =
|
481
|
+
cache_key = serializer.cache_key(adapter)
|
385
482
|
cache_store.fetch(cache_key)
|
386
483
|
end
|
387
484
|
end
|
@@ -24,6 +24,16 @@ ActiveRecord::Schema.define do
|
|
24
24
|
t.string :email
|
25
25
|
t.timestamp null: false
|
26
26
|
end
|
27
|
+
create_table :object_tags, force: true do |t|
|
28
|
+
t.string :poly_tag_id
|
29
|
+
t.string :taggable_type
|
30
|
+
t.string :taggable_id
|
31
|
+
t.timestamp null: false
|
32
|
+
end
|
33
|
+
create_table :poly_tags, force: true do |t|
|
34
|
+
t.string :phrase
|
35
|
+
t.timestamp null: false
|
36
|
+
end
|
27
37
|
create_table :pictures, force: true do |t|
|
28
38
|
t.string :title
|
29
39
|
t.string :imageable_type
|
data/test/fixtures/poro.rb
CHANGED
@@ -70,10 +70,21 @@ end
|
|
70
70
|
|
71
71
|
class Employee < ActiveRecord::Base
|
72
72
|
has_many :pictures, as: :imageable
|
73
|
+
has_many :object_tags, as: :taggable
|
74
|
+
end
|
75
|
+
|
76
|
+
class ObjectTag < ActiveRecord::Base
|
77
|
+
belongs_to :poly_tag
|
78
|
+
belongs_to :taggable, polymorphic: true
|
73
79
|
end
|
74
80
|
|
75
81
|
class Picture < ActiveRecord::Base
|
76
82
|
belongs_to :imageable, polymorphic: true
|
83
|
+
has_many :object_tags, as: :taggable
|
84
|
+
end
|
85
|
+
|
86
|
+
class PolyTag < ActiveRecord::Base
|
87
|
+
has_many :object_tags
|
77
88
|
end
|
78
89
|
|
79
90
|
module Spam; end
|
@@ -227,8 +238,9 @@ end
|
|
227
238
|
VirtualValueSerializer = Class.new(ActiveModel::Serializer) do
|
228
239
|
attributes :id
|
229
240
|
|
230
|
-
has_many :reviews, virtual_value: [{
|
231
|
-
|
241
|
+
has_many :reviews, virtual_value: [{ type: 'reviews', id: '1' },
|
242
|
+
{ type: 'reviews', id: '2' }]
|
243
|
+
has_one :maker, virtual_value: { type: 'makers', id: '1' }
|
232
244
|
|
233
245
|
def reviews
|
234
246
|
end
|
@@ -244,7 +256,23 @@ end
|
|
244
256
|
PolymorphicBelongsToSerializer = Class.new(ActiveModel::Serializer) do
|
245
257
|
attributes :id, :title
|
246
258
|
|
247
|
-
has_one :imageable, serializer: PolymorphicHasManySerializer
|
259
|
+
has_one :imageable, serializer: PolymorphicHasManySerializer, polymorphic: true
|
260
|
+
end
|
261
|
+
|
262
|
+
PolymorphicSimpleSerializer = Class.new(ActiveModel::Serializer) do
|
263
|
+
attributes :id
|
264
|
+
end
|
265
|
+
|
266
|
+
PolymorphicObjectTagSerializer = Class.new(ActiveModel::Serializer) do
|
267
|
+
attributes :id
|
268
|
+
|
269
|
+
has_many :taggable, serializer: PolymorphicSimpleSerializer, polymorphic: true
|
270
|
+
end
|
271
|
+
|
272
|
+
PolymorphicTagSerializer = Class.new(ActiveModel::Serializer) do
|
273
|
+
attributes :id, :phrase
|
274
|
+
|
275
|
+
has_many :object_tags, serializer: PolymorphicObjectTagSerializer
|
248
276
|
end
|
249
277
|
|
250
278
|
Spam::UnrelatedLinkSerializer = Class.new(ActiveModel::Serializer) do
|
@@ -239,27 +239,55 @@ module ActiveModel
|
|
239
239
|
end
|
240
240
|
end
|
241
241
|
|
242
|
+
# rubocop:disable Metrics/AbcSize
|
242
243
|
def test_conditional_associations
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
244
|
+
model = ::Model.new(true: true, false: false)
|
245
|
+
|
246
|
+
scenarios = [
|
247
|
+
{ options: { if: :true }, included: true },
|
248
|
+
{ options: { if: :false }, included: false },
|
249
|
+
{ options: { unless: :false }, included: true },
|
250
|
+
{ options: { unless: :true }, included: false },
|
251
|
+
{ options: { if: 'object.true' }, included: true },
|
252
|
+
{ options: { if: 'object.false' }, included: false },
|
253
|
+
{ options: { unless: 'object.false' }, included: true },
|
254
|
+
{ options: { unless: 'object.true' }, included: false },
|
255
|
+
{ options: { if: -> { object.true } }, included: true },
|
256
|
+
{ options: { if: -> { object.false } }, included: false },
|
257
|
+
{ options: { unless: -> { object.false } }, included: true },
|
258
|
+
{ options: { unless: -> { object.true } }, included: false },
|
259
|
+
{ options: { if: -> (s) { s.object.true } }, included: true },
|
260
|
+
{ options: { if: -> (s) { s.object.false } }, included: false },
|
261
|
+
{ options: { unless: -> (s) { s.object.false } }, included: true },
|
262
|
+
{ options: { unless: -> (s) { s.object.true } }, included: false }
|
263
|
+
]
|
264
|
+
|
265
|
+
scenarios.each do |s|
|
266
|
+
serializer = Class.new(ActiveModel::Serializer) do
|
267
|
+
belongs_to :association, s[:options]
|
268
|
+
|
269
|
+
def true
|
270
|
+
true
|
271
|
+
end
|
252
272
|
|
253
|
-
|
254
|
-
|
273
|
+
def false
|
274
|
+
false
|
275
|
+
end
|
255
276
|
end
|
277
|
+
|
278
|
+
hash = serializable(model, serializer: serializer).serializable_hash
|
279
|
+
assert_equal(s[:included], hash.key?(:association), "Error with #{s[:options]}")
|
256
280
|
end
|
281
|
+
end
|
257
282
|
|
258
|
-
|
259
|
-
|
260
|
-
|
283
|
+
def test_illegal_conditional_associations
|
284
|
+
exception = assert_raises(TypeError) do
|
285
|
+
Class.new(ActiveModel::Serializer) do
|
286
|
+
belongs_to :x, if: nil
|
287
|
+
end
|
288
|
+
end
|
261
289
|
|
262
|
-
|
290
|
+
assert_match(/:if should be a Symbol, String or Proc/, exception.message)
|
263
291
|
end
|
264
292
|
end
|
265
293
|
end
|
@@ -96,27 +96,55 @@ module ActiveModel
|
|
96
96
|
assert_equal(expected, hash)
|
97
97
|
end
|
98
98
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
99
|
+
# rubocop:disable Metrics/AbcSize
|
100
|
+
def test_conditional_associations
|
101
|
+
model = ::Model.new(true: true, false: false)
|
102
|
+
|
103
|
+
scenarios = [
|
104
|
+
{ options: { if: :true }, included: true },
|
105
|
+
{ options: { if: :false }, included: false },
|
106
|
+
{ options: { unless: :false }, included: true },
|
107
|
+
{ options: { unless: :true }, included: false },
|
108
|
+
{ options: { if: 'object.true' }, included: true },
|
109
|
+
{ options: { if: 'object.false' }, included: false },
|
110
|
+
{ options: { unless: 'object.false' }, included: true },
|
111
|
+
{ options: { unless: 'object.true' }, included: false },
|
112
|
+
{ options: { if: -> { object.true } }, included: true },
|
113
|
+
{ options: { if: -> { object.false } }, included: false },
|
114
|
+
{ options: { unless: -> { object.false } }, included: true },
|
115
|
+
{ options: { unless: -> { object.true } }, included: false },
|
116
|
+
{ options: { if: -> (s) { s.object.true } }, included: true },
|
117
|
+
{ options: { if: -> (s) { s.object.false } }, included: false },
|
118
|
+
{ options: { unless: -> (s) { s.object.false } }, included: true },
|
119
|
+
{ options: { unless: -> (s) { s.object.true } }, included: false }
|
120
|
+
]
|
121
|
+
|
122
|
+
scenarios.each do |s|
|
123
|
+
serializer = Class.new(ActiveModel::Serializer) do
|
124
|
+
attribute :attribute, s[:options]
|
125
|
+
|
126
|
+
def true
|
127
|
+
true
|
128
|
+
end
|
129
|
+
|
130
|
+
def false
|
131
|
+
false
|
132
|
+
end
|
108
133
|
end
|
109
134
|
|
110
|
-
|
111
|
-
|
112
|
-
end
|
135
|
+
hash = serializable(model, serializer: serializer).serializable_hash
|
136
|
+
assert_equal(s[:included], hash.key?(:attribute), "Error with #{s[:options]}")
|
113
137
|
end
|
138
|
+
end
|
114
139
|
|
115
|
-
|
116
|
-
|
117
|
-
|
140
|
+
def test_illegal_conditional_attributes
|
141
|
+
exception = assert_raises(TypeError) do
|
142
|
+
Class.new(ActiveModel::Serializer) do
|
143
|
+
attribute :x, if: nil
|
144
|
+
end
|
145
|
+
end
|
118
146
|
|
119
|
-
|
147
|
+
assert_match(/:if should be a Symbol, String or Proc/, exception.message)
|
120
148
|
end
|
121
149
|
end
|
122
150
|
end
|