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