active_model_serializers 0.10.0 → 0.10.9
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 +5 -5
- data/.rubocop.yml +10 -5
- data/.travis.yml +41 -21
- data/CHANGELOG.md +200 -2
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +25 -4
- data/README.md +166 -28
- data/Rakefile +5 -32
- data/active_model_serializers.gemspec +23 -25
- data/appveyor.yml +10 -6
- data/bin/rubocop +38 -0
- data/docs/README.md +2 -1
- data/docs/general/adapters.md +35 -11
- data/docs/general/caching.md +7 -1
- data/docs/general/configuration_options.md +86 -1
- data/docs/general/deserialization.md +1 -1
- data/docs/general/fields.md +31 -0
- data/docs/general/getting_started.md +1 -1
- data/docs/general/logging.md +7 -0
- data/docs/general/rendering.md +63 -25
- data/docs/general/serializers.md +137 -14
- data/docs/howto/add_pagination_links.md +16 -17
- data/docs/howto/add_relationship_links.md +140 -0
- data/docs/howto/add_root_key.md +11 -0
- data/docs/howto/grape_integration.md +42 -0
- data/docs/howto/outside_controller_use.md +12 -4
- data/docs/howto/passing_arbitrary_options.md +2 -2
- data/docs/howto/serialize_poro.md +46 -5
- data/docs/howto/test.md +2 -0
- data/docs/howto/upgrade_from_0_8_to_0_10.md +265 -0
- data/docs/integrations/ember-and-json-api.md +67 -32
- data/docs/jsonapi/schema.md +1 -1
- data/lib/action_controller/serialization.rb +15 -3
- data/lib/active_model/serializable_resource.rb +2 -0
- data/lib/active_model/serializer/adapter/attributes.rb +2 -0
- data/lib/active_model/serializer/adapter/base.rb +4 -0
- data/lib/active_model/serializer/adapter/json.rb +2 -0
- data/lib/active_model/serializer/adapter/json_api.rb +2 -0
- data/lib/active_model/serializer/adapter/null.rb +2 -0
- data/lib/active_model/serializer/adapter.rb +2 -0
- data/lib/active_model/serializer/array_serializer.rb +10 -5
- data/lib/active_model/serializer/association.rb +64 -10
- data/lib/active_model/serializer/attribute.rb +2 -0
- data/lib/active_model/serializer/belongs_to_reflection.rb +6 -3
- data/lib/active_model/serializer/collection_serializer.rb +39 -13
- data/lib/active_model/serializer/{caching.rb → concerns/caching.rb} +87 -116
- data/lib/active_model/serializer/error_serializer.rb +13 -7
- data/lib/active_model/serializer/errors_serializer.rb +27 -20
- data/lib/active_model/serializer/field.rb +2 -0
- data/lib/active_model/serializer/fieldset.rb +2 -0
- data/lib/active_model/serializer/has_many_reflection.rb +5 -3
- data/lib/active_model/serializer/has_one_reflection.rb +3 -4
- data/lib/active_model/serializer/lazy_association.rb +99 -0
- data/lib/active_model/serializer/link.rb +23 -0
- data/lib/active_model/serializer/lint.rb +136 -130
- data/lib/active_model/serializer/null.rb +2 -0
- data/lib/active_model/serializer/reflection.rb +132 -67
- data/lib/active_model/serializer/version.rb +3 -1
- data/lib/active_model/serializer.rb +308 -82
- data/lib/active_model_serializers/adapter/attributes.rb +5 -66
- data/lib/active_model_serializers/adapter/base.rb +41 -39
- data/lib/active_model_serializers/adapter/json.rb +2 -0
- data/lib/active_model_serializers/adapter/json_api/deserialization.rb +4 -2
- data/lib/active_model_serializers/adapter/json_api/error.rb +2 -0
- data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +2 -0
- data/lib/active_model_serializers/adapter/json_api/link.rb +3 -1
- data/lib/active_model_serializers/adapter/json_api/meta.rb +2 -0
- data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +49 -21
- data/lib/active_model_serializers/adapter/json_api/relationship.rb +77 -23
- data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +41 -10
- data/lib/active_model_serializers/adapter/json_api.rb +84 -65
- data/lib/active_model_serializers/adapter/null.rb +2 -0
- data/lib/active_model_serializers/adapter.rb +9 -1
- data/lib/active_model_serializers/callbacks.rb +2 -0
- data/lib/active_model_serializers/deprecate.rb +3 -2
- data/lib/active_model_serializers/deserialization.rb +4 -0
- data/lib/active_model_serializers/json_pointer.rb +2 -0
- data/lib/active_model_serializers/logging.rb +2 -0
- data/lib/active_model_serializers/lookup_chain.rb +82 -0
- data/lib/active_model_serializers/model.rb +111 -28
- data/lib/active_model_serializers/railtie.rb +7 -1
- data/lib/active_model_serializers/register_jsonapi_renderer.rb +46 -31
- data/lib/active_model_serializers/serializable_resource.rb +10 -7
- data/lib/active_model_serializers/serialization_context.rb +12 -3
- data/lib/active_model_serializers/test/schema.rb +4 -2
- data/lib/active_model_serializers/test/serializer.rb +2 -0
- data/lib/active_model_serializers/test.rb +2 -0
- data/lib/active_model_serializers.rb +35 -10
- data/lib/generators/rails/resource_override.rb +3 -1
- data/lib/generators/rails/serializer_generator.rb +6 -4
- data/lib/grape/active_model_serializers.rb +9 -5
- data/lib/grape/formatters/active_model_serializers.rb +21 -2
- data/lib/grape/helpers/active_model_serializers.rb +3 -0
- data/lib/tasks/rubocop.rake +55 -0
- data/test/action_controller/adapter_selector_test.rb +16 -5
- data/test/action_controller/explicit_serializer_test.rb +7 -4
- data/test/action_controller/json/include_test.rb +108 -27
- data/test/action_controller/json_api/deserialization_test.rb +3 -1
- data/test/action_controller/json_api/errors_test.rb +10 -9
- data/test/action_controller/json_api/fields_test.rb +68 -0
- data/test/action_controller/json_api/linked_test.rb +31 -24
- data/test/action_controller/json_api/pagination_test.rb +33 -23
- data/test/action_controller/json_api/transform_test.rb +13 -3
- data/test/action_controller/lookup_proc_test.rb +51 -0
- data/test/action_controller/namespace_lookup_test.rb +234 -0
- data/test/action_controller/serialization_scope_name_test.rb +14 -6
- data/test/action_controller/serialization_test.rb +23 -12
- data/test/active_model_serializers/adapter_for_test.rb +2 -0
- data/test/active_model_serializers/json_pointer_test.rb +17 -13
- data/test/active_model_serializers/logging_test.rb +2 -0
- data/test/active_model_serializers/model_test.rb +139 -4
- data/test/active_model_serializers/railtie_test_isolated.rb +14 -7
- data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +163 -0
- data/test/active_model_serializers/serialization_context_test_isolated.rb +25 -10
- data/test/active_model_serializers/test/schema_test.rb +5 -2
- data/test/active_model_serializers/test/serializer_test.rb +2 -0
- data/test/active_record_test.rb +2 -0
- data/test/adapter/attributes_test.rb +42 -0
- data/test/adapter/deprecation_test.rb +2 -0
- data/test/adapter/json/belongs_to_test.rb +2 -0
- data/test/adapter/json/collection_test.rb +16 -0
- data/test/adapter/json/has_many_test.rb +12 -2
- data/test/adapter/json/transform_test.rb +17 -15
- data/test/adapter/json_api/belongs_to_test.rb +2 -0
- data/test/adapter/json_api/collection_test.rb +6 -3
- data/test/adapter/json_api/errors_test.rb +19 -19
- data/test/adapter/json_api/fields_test.rb +14 -3
- data/test/adapter/json_api/has_many_explicit_serializer_test.rb +2 -0
- data/test/adapter/json_api/has_many_test.rb +51 -20
- data/test/adapter/json_api/has_one_test.rb +2 -0
- data/test/adapter/json_api/include_data_if_sideloaded_test.rb +215 -0
- data/test/adapter/json_api/json_api_test.rb +7 -7
- data/test/adapter/json_api/linked_test.rb +35 -12
- data/test/adapter/json_api/links_test.rb +22 -3
- data/test/adapter/json_api/pagination_links_test.rb +55 -13
- data/test/adapter/json_api/parse_test.rb +3 -1
- data/test/adapter/json_api/relationship_test.rb +311 -73
- data/test/adapter/json_api/resource_meta_test.rb +5 -3
- data/test/adapter/json_api/toplevel_jsonapi_test.rb +2 -0
- data/test/adapter/json_api/transform_test.rb +265 -253
- data/test/adapter/json_api/type_test.rb +170 -36
- data/test/adapter/json_test.rb +10 -7
- data/test/adapter/null_test.rb +3 -2
- data/test/adapter/polymorphic_test.rb +54 -5
- data/test/adapter_test.rb +3 -1
- data/test/array_serializer_test.rb +2 -0
- data/test/benchmark/app.rb +3 -1
- data/test/benchmark/benchmarking_support.rb +3 -1
- data/test/benchmark/bm_active_record.rb +83 -0
- data/test/benchmark/bm_adapter.rb +40 -0
- data/test/benchmark/bm_caching.rb +18 -16
- data/test/benchmark/bm_lookup_chain.rb +85 -0
- data/test/benchmark/bm_transform.rb +23 -10
- data/test/benchmark/controllers.rb +18 -17
- data/test/benchmark/fixtures.rb +74 -72
- data/test/cache_test.rb +301 -69
- data/test/collection_serializer_test.rb +33 -14
- data/test/fixtures/active_record.rb +47 -10
- data/test/fixtures/poro.rb +128 -183
- data/test/generators/scaffold_controller_generator_test.rb +2 -0
- data/test/generators/serializer_generator_test.rb +25 -5
- data/test/grape_test.rb +172 -56
- data/test/lint_test.rb +3 -1
- data/test/logger_test.rb +15 -11
- data/test/poro_test.rb +2 -0
- data/test/serializable_resource_test.rb +20 -22
- data/test/serializers/association_macros_test.rb +5 -2
- data/test/serializers/associations_test.rb +274 -49
- data/test/serializers/attribute_test.rb +7 -3
- data/test/serializers/attributes_test.rb +3 -1
- data/test/serializers/caching_configuration_test_isolated.rb +8 -6
- data/test/serializers/configuration_test.rb +2 -0
- data/test/serializers/fieldset_test.rb +3 -1
- data/test/serializers/meta_test.rb +14 -6
- data/test/serializers/options_test.rb +19 -6
- data/test/serializers/read_attribute_for_serialization_test.rb +5 -3
- data/test/serializers/reflection_test.rb +481 -0
- data/test/serializers/root_test.rb +3 -1
- data/test/serializers/serialization_test.rb +4 -2
- data/test/serializers/serializer_for_test.rb +14 -10
- data/test/serializers/serializer_for_with_namespace_test.rb +90 -0
- data/test/support/isolated_unit.rb +11 -4
- data/test/support/rails5_shims.rb +10 -2
- data/test/support/rails_app.rb +4 -9
- data/test/support/serialization_testing.rb +33 -5
- data/test/test_helper.rb +15 -0
- metadata +126 -46
- data/.rubocop_todo.yml +0 -167
- data/docs/ARCHITECTURE.md +0 -126
- data/lib/active_model/serializer/associations.rb +0 -100
- data/lib/active_model/serializer/attributes.rb +0 -82
- data/lib/active_model/serializer/collection_reflection.rb +0 -7
- data/lib/active_model/serializer/configuration.rb +0 -35
- data/lib/active_model/serializer/include_tree.rb +0 -111
- data/lib/active_model/serializer/links.rb +0 -35
- data/lib/active_model/serializer/meta.rb +0 -29
- data/lib/active_model/serializer/singular_reflection.rb +0 -7
- data/lib/active_model/serializer/type.rb +0 -25
- data/lib/active_model_serializers/key_transform.rb +0 -70
- data/test/active_model_serializers/key_transform_test.rb +0 -263
- data/test/adapter/json_api/has_many_embed_ids_test.rb +0 -43
- data/test/adapter/json_api/relationships_test.rb +0 -199
- data/test/adapter/json_api/resource_identifier_test.rb +0 -85
- data/test/include_tree/from_include_args_test.rb +0 -26
- data/test/include_tree/from_string_test.rb +0 -94
- data/test/include_tree/include_args_to_hash_test.rb +0 -64
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'test_helper'
|
|
2
4
|
|
|
3
5
|
module ActiveModelSerializers
|
|
@@ -58,9 +60,10 @@ module ActiveModelSerializers
|
|
|
58
60
|
|
|
59
61
|
def test_limiting_fields
|
|
60
62
|
actual = ActiveModelSerializers::SerializableResource.new(
|
|
61
|
-
[@first_post, @second_post],
|
|
62
|
-
|
|
63
|
-
|
|
63
|
+
[@first_post, @second_post],
|
|
64
|
+
adapter: :json_api,
|
|
65
|
+
fields: { posts: %w(title comments blog author) }
|
|
66
|
+
).serializable_hash
|
|
64
67
|
expected = [
|
|
65
68
|
{
|
|
66
69
|
id: '1',
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'test_helper'
|
|
2
4
|
|
|
3
5
|
module ActiveModelSerializers
|
|
@@ -12,8 +14,8 @@ module ActiveModelSerializers
|
|
|
12
14
|
|
|
13
15
|
def test_active_model_with_error
|
|
14
16
|
options = {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
serializer: ActiveModel::Serializer::ErrorSerializer,
|
|
18
|
+
adapter: :json_api
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
@resource.errors.add(:name, 'cannot be nil')
|
|
@@ -22,22 +24,21 @@ module ActiveModelSerializers
|
|
|
22
24
|
assert_equal serializable_resource.serializer_instance.attributes, {}
|
|
23
25
|
assert_equal serializable_resource.serializer_instance.object, @resource
|
|
24
26
|
|
|
25
|
-
expected_errors_object =
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
{
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
]
|
|
27
|
+
expected_errors_object = {
|
|
28
|
+
errors: [
|
|
29
|
+
{
|
|
30
|
+
source: { pointer: '/data/attributes/name' },
|
|
31
|
+
detail: 'cannot be nil'
|
|
32
|
+
}
|
|
33
|
+
]
|
|
33
34
|
}
|
|
34
35
|
assert_equal serializable_resource.as_json, expected_errors_object
|
|
35
36
|
end
|
|
36
37
|
|
|
37
38
|
def test_active_model_with_multiple_errors
|
|
38
39
|
options = {
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
serializer: ActiveModel::Serializer::ErrorSerializer,
|
|
41
|
+
adapter: :json_api
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
@resource.errors.add(:name, 'cannot be nil')
|
|
@@ -48,13 +49,12 @@ module ActiveModelSerializers
|
|
|
48
49
|
assert_equal serializable_resource.serializer_instance.attributes, {}
|
|
49
50
|
assert_equal serializable_resource.serializer_instance.object, @resource
|
|
50
51
|
|
|
51
|
-
expected_errors_object =
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
]
|
|
52
|
+
expected_errors_object = {
|
|
53
|
+
errors: [
|
|
54
|
+
{ source: { pointer: '/data/attributes/name' }, detail: 'cannot be nil' },
|
|
55
|
+
{ source: { pointer: '/data/attributes/name' }, detail: 'must be longer' },
|
|
56
|
+
{ source: { pointer: '/data/attributes/id' }, detail: 'must be a uuid' }
|
|
57
|
+
]
|
|
58
58
|
}
|
|
59
59
|
assert_equal serializable_resource.as_json, expected_errors_object
|
|
60
60
|
end
|
|
@@ -1,10 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'test_helper'
|
|
2
4
|
|
|
3
5
|
module ActiveModelSerializers
|
|
4
6
|
module Adapter
|
|
5
7
|
class JsonApi
|
|
6
8
|
class FieldsTest < ActiveSupport::TestCase
|
|
7
|
-
Post
|
|
9
|
+
class Post < ::Model
|
|
10
|
+
attributes :title, :body
|
|
11
|
+
associations :author, :comments
|
|
12
|
+
end
|
|
13
|
+
class Author < ::Model
|
|
14
|
+
attributes :name, :birthday
|
|
15
|
+
end
|
|
16
|
+
class Comment < ::Model
|
|
17
|
+
attributes :body
|
|
18
|
+
associations :author, :post
|
|
19
|
+
end
|
|
20
|
+
|
|
8
21
|
class PostSerializer < ActiveModel::Serializer
|
|
9
22
|
type 'posts'
|
|
10
23
|
attributes :title, :body
|
|
@@ -12,13 +25,11 @@ module ActiveModelSerializers
|
|
|
12
25
|
has_many :comments
|
|
13
26
|
end
|
|
14
27
|
|
|
15
|
-
Author = Class.new(::Model)
|
|
16
28
|
class AuthorSerializer < ActiveModel::Serializer
|
|
17
29
|
type 'authors'
|
|
18
30
|
attributes :name, :birthday
|
|
19
31
|
end
|
|
20
32
|
|
|
21
|
-
Comment = Class.new(::Model)
|
|
22
33
|
class CommentSerializer < ActiveModel::Serializer
|
|
23
34
|
type 'comments'
|
|
24
35
|
attributes :body
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'test_helper'
|
|
2
4
|
|
|
3
5
|
module ActiveModelSerializers
|
|
4
6
|
module Adapter
|
|
5
7
|
class JsonApi
|
|
6
8
|
class HasManyTest < ActiveSupport::TestCase
|
|
9
|
+
class ModelWithoutSerializer < ::Model
|
|
10
|
+
attributes :id, :name
|
|
11
|
+
end
|
|
12
|
+
|
|
7
13
|
def setup
|
|
8
14
|
ActionController::Base.cache_store.clear
|
|
9
15
|
@author = Author.new(id: 1, name: 'Steve K.')
|
|
@@ -26,7 +32,7 @@ module ActiveModelSerializers
|
|
|
26
32
|
@blog.articles = [@post]
|
|
27
33
|
@post.blog = @blog
|
|
28
34
|
@post_without_comments.blog = nil
|
|
29
|
-
@tag =
|
|
35
|
+
@tag = ModelWithoutSerializer.new(id: 1, name: '#hash_tag')
|
|
30
36
|
@post.tags = [@tag]
|
|
31
37
|
@serializer = PostSerializer.new(@post)
|
|
32
38
|
@adapter = ActiveModelSerializers::Adapter::JsonApi.new(@serializer)
|
|
@@ -40,6 +46,27 @@ module ActiveModelSerializers
|
|
|
40
46
|
assert_equal(expected, @adapter.serializable_hash[:data][:relationships][:comments])
|
|
41
47
|
end
|
|
42
48
|
|
|
49
|
+
test 'relationships can be whitelisted via fields' do
|
|
50
|
+
@adapter = ActiveModelSerializers::Adapter::JsonApi.new(@serializer, fields: { posts: [:author] })
|
|
51
|
+
result = @adapter.serializable_hash
|
|
52
|
+
expected = {
|
|
53
|
+
data: {
|
|
54
|
+
id: '1',
|
|
55
|
+
type: 'posts',
|
|
56
|
+
relationships: {
|
|
57
|
+
author: {
|
|
58
|
+
data: {
|
|
59
|
+
id: '1',
|
|
60
|
+
type: 'authors'
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
assert_equal expected, result
|
|
68
|
+
end
|
|
69
|
+
|
|
43
70
|
def test_includes_linked_comments
|
|
44
71
|
@adapter = ActiveModelSerializers::Adapter::JsonApi.new(@serializer, include: [:comments])
|
|
45
72
|
expected = [{
|
|
@@ -108,18 +135,22 @@ module ActiveModelSerializers
|
|
|
108
135
|
end
|
|
109
136
|
|
|
110
137
|
def test_has_many_with_no_serializer
|
|
111
|
-
|
|
138
|
+
post_serializer_class = Class.new(ActiveModel::Serializer) do
|
|
139
|
+
attributes :id
|
|
140
|
+
has_many :tags
|
|
141
|
+
end
|
|
142
|
+
serializer = post_serializer_class.new(@post)
|
|
112
143
|
adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer)
|
|
113
144
|
|
|
114
145
|
assert_equal({
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
146
|
+
data: {
|
|
147
|
+
id: '1',
|
|
148
|
+
type: 'posts',
|
|
149
|
+
relationships: {
|
|
150
|
+
tags: { data: [@tag.as_json] }
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}, adapter.serializable_hash)
|
|
123
154
|
end
|
|
124
155
|
|
|
125
156
|
def test_has_many_with_virtual_value
|
|
@@ -127,16 +158,16 @@ module ActiveModelSerializers
|
|
|
127
158
|
adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer)
|
|
128
159
|
|
|
129
160
|
assert_equal({
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
161
|
+
data: {
|
|
162
|
+
id: '1',
|
|
163
|
+
type: 'virtual-values',
|
|
164
|
+
relationships: {
|
|
165
|
+
maker: { data: { type: 'makers', id: '1' } },
|
|
166
|
+
reviews: { data: [{ type: 'reviews', id: '1' },
|
|
167
|
+
{ type: 'reviews', id: '2' }] }
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}, adapter.serializable_hash)
|
|
140
171
|
end
|
|
141
172
|
end
|
|
142
173
|
end
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
|
|
5
|
+
module ActiveModel
|
|
6
|
+
class Serializer
|
|
7
|
+
module Adapter
|
|
8
|
+
class JsonApi
|
|
9
|
+
class IncludeParamTest < ActiveSupport::TestCase
|
|
10
|
+
IncludeParamAuthor = Class.new(::Model) do
|
|
11
|
+
associations :tags, :posts, :roles
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class CustomCommentLoader
|
|
15
|
+
def all
|
|
16
|
+
[{ foo: 'bar' }]
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
class Tag < ::Model
|
|
20
|
+
attributes :id, :name
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class TagSerializer < ActiveModel::Serializer
|
|
24
|
+
type 'tags'
|
|
25
|
+
attributes :id, :name
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class PostWithTagsSerializer < ActiveModel::Serializer
|
|
29
|
+
type 'posts'
|
|
30
|
+
attributes :id
|
|
31
|
+
has_many :tags
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
class IncludeParamAuthorSerializer < ActiveModel::Serializer
|
|
35
|
+
class_attribute :comment_loader
|
|
36
|
+
|
|
37
|
+
has_many :tags, serializer: TagSerializer do
|
|
38
|
+
link :self, '//example.com/link_author/relationships/tags'
|
|
39
|
+
include_data :if_sideloaded
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
has_many :unlinked_tags, serializer: TagSerializer do
|
|
43
|
+
include_data :if_sideloaded
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
has_many :posts, serializer: PostWithTagsSerializer do
|
|
47
|
+
include_data :if_sideloaded
|
|
48
|
+
end
|
|
49
|
+
has_many :locations do
|
|
50
|
+
include_data :if_sideloaded
|
|
51
|
+
end
|
|
52
|
+
has_many :comments do
|
|
53
|
+
include_data :if_sideloaded
|
|
54
|
+
IncludeParamAuthorSerializer.comment_loader.all
|
|
55
|
+
end
|
|
56
|
+
has_many :roles, key: :granted_roles do
|
|
57
|
+
include_data :if_sideloaded
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def setup
|
|
62
|
+
IncludeParamAuthorSerializer.comment_loader = Class.new(CustomCommentLoader).new
|
|
63
|
+
@tag = Tag.new(id: 1337, name: 'mytag')
|
|
64
|
+
@role = Role.new(id: 1337, name: 'myrole')
|
|
65
|
+
@author = IncludeParamAuthor.new(
|
|
66
|
+
id: 1337,
|
|
67
|
+
tags: [@tag],
|
|
68
|
+
roles: [@role]
|
|
69
|
+
)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def test_relationship_not_loaded_when_not_included
|
|
73
|
+
expected = {
|
|
74
|
+
links: {
|
|
75
|
+
self: '//example.com/link_author/relationships/tags'
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@author.define_singleton_method(:read_attribute_for_serialization) do |attr|
|
|
80
|
+
fail 'should not be called' if attr == :tags
|
|
81
|
+
super(attr)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
assert_relationship(:tags, expected)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def test_relationship_included
|
|
88
|
+
expected = {
|
|
89
|
+
data: [
|
|
90
|
+
{
|
|
91
|
+
id: '1337',
|
|
92
|
+
type: 'tags'
|
|
93
|
+
}
|
|
94
|
+
],
|
|
95
|
+
links: {
|
|
96
|
+
self: '//example.com/link_author/relationships/tags'
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
assert_relationship(:tags, expected, include: :tags)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def test_sideloads_included
|
|
104
|
+
expected = [
|
|
105
|
+
{
|
|
106
|
+
id: '1337',
|
|
107
|
+
type: 'tags',
|
|
108
|
+
attributes: { name: 'mytag' }
|
|
109
|
+
}
|
|
110
|
+
]
|
|
111
|
+
hash = result(include: :tags)
|
|
112
|
+
assert_equal(expected, hash[:included])
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def test_sideloads_included_when_using_key
|
|
116
|
+
expected = [
|
|
117
|
+
{
|
|
118
|
+
id: '1337',
|
|
119
|
+
type: 'roles',
|
|
120
|
+
attributes: {
|
|
121
|
+
name: 'myrole',
|
|
122
|
+
description: nil,
|
|
123
|
+
slug: 'myrole-1337'
|
|
124
|
+
},
|
|
125
|
+
relationships: {
|
|
126
|
+
author: { data: nil }
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
]
|
|
130
|
+
|
|
131
|
+
hash = result(include: :granted_roles)
|
|
132
|
+
assert_equal(expected, hash[:included])
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def test_sideloads_not_included_when_using_name_when_key_defined
|
|
136
|
+
hash = result(include: :roles)
|
|
137
|
+
assert_nil(hash[:included])
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def test_nested_relationship
|
|
141
|
+
expected = {
|
|
142
|
+
data: [
|
|
143
|
+
{
|
|
144
|
+
id: '1337',
|
|
145
|
+
type: 'tags'
|
|
146
|
+
}
|
|
147
|
+
],
|
|
148
|
+
links: {
|
|
149
|
+
self: '//example.com/link_author/relationships/tags'
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
expected_no_data = {
|
|
154
|
+
links: {
|
|
155
|
+
self: '//example.com/link_author/relationships/tags'
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
assert_relationship(:tags, expected, include: [:tags, { posts: :tags }])
|
|
160
|
+
|
|
161
|
+
@author.define_singleton_method(:read_attribute_for_serialization) do |attr|
|
|
162
|
+
fail 'should not be called' if attr == :tags
|
|
163
|
+
super(attr)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
assert_relationship(:tags, expected_no_data, include: { posts: :tags })
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def test_include_params_with_no_block
|
|
170
|
+
@author.define_singleton_method(:read_attribute_for_serialization) do |attr|
|
|
171
|
+
fail 'should not be called' if attr == :locations
|
|
172
|
+
super(attr)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
expected = { meta: {} }
|
|
176
|
+
|
|
177
|
+
assert_relationship(:locations, expected)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def test_block_relationship
|
|
181
|
+
expected = {
|
|
182
|
+
data: [
|
|
183
|
+
{ 'foo' => 'bar' }
|
|
184
|
+
]
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
assert_relationship(:comments, expected, include: [:comments])
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def test_node_not_included_when_no_link
|
|
191
|
+
expected = { meta: {} }
|
|
192
|
+
assert_relationship(:unlinked_tags, expected, key_transform: :unaltered)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
private
|
|
196
|
+
|
|
197
|
+
def assert_relationship(relationship_name, expected, opts = {})
|
|
198
|
+
actual = relationship_data(relationship_name, opts)
|
|
199
|
+
assert_equal(expected, actual)
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def result(opts)
|
|
203
|
+
opts = { adapter: :json_api }.merge(opts)
|
|
204
|
+
serializable(@author, opts).serializable_hash
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def relationship_data(relationship_name, opts = {})
|
|
208
|
+
hash = result(opts)
|
|
209
|
+
hash[:data][:relationships][relationship_name]
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'test_helper'
|
|
2
4
|
|
|
3
5
|
module ActiveModelSerializers
|
|
@@ -22,13 +24,11 @@ module ActiveModelSerializers
|
|
|
22
24
|
adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer)
|
|
23
25
|
|
|
24
26
|
assert_equal({
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
site: { data: { type: 'blogs', id: '1' } }
|
|
31
|
-
}, adapter.serializable_hash[:data][:relationships])
|
|
27
|
+
reviews: { data: [{ type: 'comments', id: '1' },
|
|
28
|
+
{ type: 'comments', id: '2' }] },
|
|
29
|
+
writer: { data: { type: 'authors', id: '1' } },
|
|
30
|
+
site: { data: { type: 'blogs', id: '1' } }
|
|
31
|
+
}, adapter.serializable_hash[:data][:relationships])
|
|
32
32
|
end
|
|
33
33
|
end
|
|
34
34
|
end
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'test_helper'
|
|
2
4
|
|
|
3
|
-
NestedPost
|
|
5
|
+
class NestedPost < ::Model; associations :nested_posts end
|
|
4
6
|
class NestedPostSerializer < ActiveModel::Serializer
|
|
5
7
|
has_many :nested_posts
|
|
6
8
|
end
|
|
7
|
-
|
|
8
9
|
module ActiveModelSerializers
|
|
9
10
|
module Adapter
|
|
10
11
|
class JsonApi
|
|
@@ -17,7 +18,7 @@ module ActiveModelSerializers
|
|
|
17
18
|
@first_post = Post.new(id: 10, title: 'Hello!!', body: 'Hello, world!!')
|
|
18
19
|
@second_post = Post.new(id: 20, title: 'New Post', body: 'Body')
|
|
19
20
|
@third_post = Post.new(id: 30, title: 'Yet Another Post', body: 'Body')
|
|
20
|
-
@blog = Blog.new(
|
|
21
|
+
@blog = Blog.new(name: 'AMS Blog')
|
|
21
22
|
@first_comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
|
|
22
23
|
@second_comment = Comment.new(id: 2, body: 'ZOMG ANOTHER COMMENT')
|
|
23
24
|
@first_post.blog = @blog
|
|
@@ -224,6 +225,25 @@ module ActiveModelSerializers
|
|
|
224
225
|
assert_equal expected, relationships
|
|
225
226
|
end
|
|
226
227
|
|
|
228
|
+
def test_underscore_model_namespace_with_namespace_separator_for_linked_resource_type
|
|
229
|
+
spammy_post = Post.new(id: 123)
|
|
230
|
+
spammy_post.related = [Spam::UnrelatedLink.new(id: 456)]
|
|
231
|
+
serializer = SpammyPostSerializer.new(spammy_post)
|
|
232
|
+
adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer)
|
|
233
|
+
relationships = with_namespace_separator '--' do
|
|
234
|
+
adapter.serializable_hash[:data][:relationships]
|
|
235
|
+
end
|
|
236
|
+
expected = {
|
|
237
|
+
related: {
|
|
238
|
+
data: [{
|
|
239
|
+
type: 'spam--unrelated-links',
|
|
240
|
+
id: '456'
|
|
241
|
+
}]
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
assert_equal expected, relationships
|
|
245
|
+
end
|
|
246
|
+
|
|
227
247
|
def test_multiple_references_to_same_resource
|
|
228
248
|
serializer = ActiveModel::Serializer::CollectionSerializer.new([@first_comment, @second_comment])
|
|
229
249
|
adapter = ActiveModelSerializers::Adapter::JsonApi.new(
|
|
@@ -283,8 +303,8 @@ module ActiveModelSerializers
|
|
|
283
303
|
end
|
|
284
304
|
|
|
285
305
|
class NoDuplicatesTest < ActiveSupport::TestCase
|
|
286
|
-
Post
|
|
287
|
-
Author
|
|
306
|
+
class Post < ::Model; associations :author end
|
|
307
|
+
class Author < ::Model; associations :posts, :roles, :bio end
|
|
288
308
|
|
|
289
309
|
class PostSerializer < ActiveModel::Serializer
|
|
290
310
|
type 'posts'
|
|
@@ -303,8 +323,8 @@ module ActiveModelSerializers
|
|
|
303
323
|
@author.posts << @post1
|
|
304
324
|
@author.posts << @post2
|
|
305
325
|
|
|
306
|
-
@nestedpost1 =
|
|
307
|
-
@nestedpost2 =
|
|
326
|
+
@nestedpost1 = NestedPost.new(id: 1, nested_posts: [])
|
|
327
|
+
@nestedpost2 = NestedPost.new(id: 2, nested_posts: [])
|
|
308
328
|
@nestedpost1.nested_posts << @nestedpost1
|
|
309
329
|
@nestedpost1.nested_posts << @nestedpost2
|
|
310
330
|
@nestedpost2.nested_posts << @nestedpost1
|
|
@@ -341,9 +361,10 @@ module ActiveModelSerializers
|
|
|
341
361
|
|
|
342
362
|
def test_no_duplicates_collection
|
|
343
363
|
hash = ActiveModelSerializers::SerializableResource.new(
|
|
344
|
-
[@post1, @post2],
|
|
345
|
-
|
|
346
|
-
|
|
364
|
+
[@post1, @post2],
|
|
365
|
+
adapter: :json_api,
|
|
366
|
+
include: '*.*'
|
|
367
|
+
).serializable_hash
|
|
347
368
|
expected = [
|
|
348
369
|
{
|
|
349
370
|
type: 'authors', id: '1',
|
|
@@ -364,7 +385,8 @@ module ActiveModelSerializers
|
|
|
364
385
|
hash = ActiveModelSerializers::SerializableResource.new(
|
|
365
386
|
@nestedpost1,
|
|
366
387
|
adapter: :json_api,
|
|
367
|
-
include: '*'
|
|
388
|
+
include: '*'
|
|
389
|
+
).serializable_hash
|
|
368
390
|
expected = [
|
|
369
391
|
type: 'nested-posts', id: '2',
|
|
370
392
|
relationships: {
|
|
@@ -383,7 +405,8 @@ module ActiveModelSerializers
|
|
|
383
405
|
hash = ActiveModelSerializers::SerializableResource.new(
|
|
384
406
|
[@nestedpost1, @nestedpost2],
|
|
385
407
|
adapter: :json_api,
|
|
386
|
-
include: '*'
|
|
408
|
+
include: '*'
|
|
409
|
+
).serializable_hash
|
|
387
410
|
assert_nil(hash[:included])
|
|
388
411
|
end
|
|
389
412
|
end
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'test_helper'
|
|
2
4
|
|
|
3
5
|
module ActiveModelSerializers
|
|
4
6
|
module Adapter
|
|
5
7
|
class JsonApi
|
|
6
8
|
class LinksTest < ActiveSupport::TestCase
|
|
7
|
-
LinkAuthor
|
|
9
|
+
class LinkAuthor < ::Model; associations :posts end
|
|
8
10
|
class LinkAuthorSerializer < ActiveModel::Serializer
|
|
9
11
|
link :self do
|
|
10
12
|
href "http://example.com/link_author/#{object.id}"
|
|
@@ -17,6 +19,21 @@ module ActiveModelSerializers
|
|
|
17
19
|
link :yet_another do
|
|
18
20
|
"http://example.com/resource/#{object.id}"
|
|
19
21
|
end
|
|
22
|
+
link :conditional1, if: -> { instance_truth } do
|
|
23
|
+
"http://example.com/conditional1/#{object.id}"
|
|
24
|
+
end
|
|
25
|
+
link :conditional2, if: :instance_falsey do
|
|
26
|
+
"http://example.com/conditional2/#{object.id}"
|
|
27
|
+
end
|
|
28
|
+
link(:nil) { nil }
|
|
29
|
+
|
|
30
|
+
def instance_truth
|
|
31
|
+
true
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def instance_falsey
|
|
35
|
+
false
|
|
36
|
+
end
|
|
20
37
|
end
|
|
21
38
|
|
|
22
39
|
def setup
|
|
@@ -40,7 +57,8 @@ module ActiveModelSerializers
|
|
|
40
57
|
stuff: 'value'
|
|
41
58
|
}
|
|
42
59
|
}
|
|
43
|
-
}
|
|
60
|
+
}
|
|
61
|
+
).serializable_hash
|
|
44
62
|
expected = {
|
|
45
63
|
self: {
|
|
46
64
|
href: 'http://example.com/posts',
|
|
@@ -83,7 +101,8 @@ module ActiveModelSerializers
|
|
|
83
101
|
:"link-authors" => 'http://example.com/link_authors',
|
|
84
102
|
resource: 'http://example.com/resource',
|
|
85
103
|
posts: 'http://example.com/link_authors/1337/posts',
|
|
86
|
-
:"yet-another" => 'http://example.com/resource/1337'
|
|
104
|
+
:"yet-another" => 'http://example.com/resource/1337',
|
|
105
|
+
conditional1: 'http://example.com/conditional1/1337'
|
|
87
106
|
}
|
|
88
107
|
assert_equal(expected, hash[:data][:links])
|
|
89
108
|
end
|