active_model_serializers_custom 0.10.90
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 +7 -0
- data/.github/ISSUE_TEMPLATE.md +29 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +15 -0
- data/.gitignore +35 -0
- data/.rubocop.yml +109 -0
- data/.simplecov +110 -0
- data/.travis.yml +63 -0
- data/CHANGELOG.md +727 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/CONTRIBUTING.md +105 -0
- data/Gemfile +74 -0
- data/MIT-LICENSE +22 -0
- data/README.md +305 -0
- data/Rakefile +76 -0
- data/active_model_serializers.gemspec +64 -0
- data/appveyor.yml +28 -0
- data/bin/bench +171 -0
- data/bin/bench_regression +316 -0
- data/bin/rubocop +38 -0
- data/bin/serve_benchmark +39 -0
- data/docs/README.md +41 -0
- data/docs/STYLE.md +58 -0
- data/docs/general/adapters.md +269 -0
- data/docs/general/caching.md +58 -0
- data/docs/general/configuration_options.md +185 -0
- data/docs/general/deserialization.md +100 -0
- data/docs/general/fields.md +31 -0
- data/docs/general/getting_started.md +133 -0
- data/docs/general/instrumentation.md +40 -0
- data/docs/general/key_transforms.md +40 -0
- data/docs/general/logging.md +21 -0
- data/docs/general/rendering.md +293 -0
- data/docs/general/serializers.md +495 -0
- data/docs/how-open-source-maintained.jpg +0 -0
- data/docs/howto/add_pagination_links.md +138 -0
- data/docs/howto/add_relationship_links.md +140 -0
- data/docs/howto/add_root_key.md +62 -0
- data/docs/howto/grape_integration.md +42 -0
- data/docs/howto/outside_controller_use.md +66 -0
- data/docs/howto/passing_arbitrary_options.md +27 -0
- data/docs/howto/serialize_poro.md +73 -0
- data/docs/howto/test.md +154 -0
- data/docs/howto/upgrade_from_0_8_to_0_10.md +265 -0
- data/docs/integrations/ember-and-json-api.md +147 -0
- data/docs/integrations/grape.md +19 -0
- data/docs/jsonapi/errors.md +56 -0
- data/docs/jsonapi/schema.md +151 -0
- data/docs/jsonapi/schema/schema.json +366 -0
- data/docs/rfcs/0000-namespace.md +106 -0
- data/docs/rfcs/template.md +15 -0
- data/lib/action_controller/serialization.rb +76 -0
- data/lib/active_model/serializable_resource.rb +13 -0
- data/lib/active_model/serializer.rb +418 -0
- data/lib/active_model/serializer/adapter.rb +26 -0
- data/lib/active_model/serializer/adapter/attributes.rb +17 -0
- data/lib/active_model/serializer/adapter/base.rb +20 -0
- data/lib/active_model/serializer/adapter/json.rb +17 -0
- data/lib/active_model/serializer/adapter/json_api.rb +17 -0
- data/lib/active_model/serializer/adapter/null.rb +17 -0
- data/lib/active_model/serializer/array_serializer.rb +14 -0
- data/lib/active_model/serializer/association.rb +91 -0
- data/lib/active_model/serializer/attribute.rb +27 -0
- data/lib/active_model/serializer/belongs_to_reflection.rb +13 -0
- data/lib/active_model/serializer/collection_serializer.rb +90 -0
- data/lib/active_model/serializer/concerns/caching.rb +304 -0
- data/lib/active_model/serializer/error_serializer.rb +16 -0
- data/lib/active_model/serializer/errors_serializer.rb +34 -0
- data/lib/active_model/serializer/field.rb +92 -0
- data/lib/active_model/serializer/fieldset.rb +33 -0
- data/lib/active_model/serializer/has_many_reflection.rb +12 -0
- data/lib/active_model/serializer/has_one_reflection.rb +9 -0
- 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 +152 -0
- data/lib/active_model/serializer/null.rb +19 -0
- data/lib/active_model/serializer/reflection.rb +212 -0
- data/lib/active_model/serializer/version.rb +7 -0
- data/lib/active_model_serializers.rb +63 -0
- data/lib/active_model_serializers/adapter.rb +100 -0
- data/lib/active_model_serializers/adapter/attributes.rb +15 -0
- data/lib/active_model_serializers/adapter/base.rb +85 -0
- data/lib/active_model_serializers/adapter/json.rb +23 -0
- data/lib/active_model_serializers/adapter/json_api.rb +535 -0
- data/lib/active_model_serializers/adapter/json_api/deserialization.rb +215 -0
- data/lib/active_model_serializers/adapter/json_api/error.rb +98 -0
- data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +51 -0
- data/lib/active_model_serializers/adapter/json_api/link.rb +85 -0
- data/lib/active_model_serializers/adapter/json_api/meta.rb +39 -0
- data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +90 -0
- data/lib/active_model_serializers/adapter/json_api/relationship.rb +106 -0
- data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +68 -0
- data/lib/active_model_serializers/adapter/null.rb +11 -0
- data/lib/active_model_serializers/callbacks.rb +57 -0
- data/lib/active_model_serializers/deprecate.rb +56 -0
- data/lib/active_model_serializers/deserialization.rb +17 -0
- data/lib/active_model_serializers/json_pointer.rb +16 -0
- data/lib/active_model_serializers/logging.rb +124 -0
- data/lib/active_model_serializers/lookup_chain.rb +82 -0
- data/lib/active_model_serializers/model.rb +132 -0
- data/lib/active_model_serializers/railtie.rb +52 -0
- data/lib/active_model_serializers/register_jsonapi_renderer.rb +80 -0
- data/lib/active_model_serializers/serializable_resource.rb +84 -0
- data/lib/active_model_serializers/serialization_context.rb +41 -0
- data/lib/active_model_serializers/test.rb +9 -0
- data/lib/active_model_serializers/test/schema.rb +140 -0
- data/lib/active_model_serializers/test/serializer.rb +127 -0
- data/lib/generators/rails/USAGE +6 -0
- data/lib/generators/rails/resource_override.rb +12 -0
- data/lib/generators/rails/serializer_generator.rb +38 -0
- data/lib/generators/rails/templates/serializer.rb.erb +8 -0
- data/lib/grape/active_model_serializers.rb +18 -0
- data/lib/grape/formatters/active_model_serializers.rb +34 -0
- data/lib/grape/helpers/active_model_serializers.rb +19 -0
- data/lib/tasks/rubocop.rake +55 -0
- data/test/action_controller/adapter_selector_test.rb +64 -0
- data/test/action_controller/explicit_serializer_test.rb +137 -0
- data/test/action_controller/json/include_test.rb +248 -0
- data/test/action_controller/json_api/deserialization_test.rb +114 -0
- data/test/action_controller/json_api/errors_test.rb +42 -0
- data/test/action_controller/json_api/fields_test.rb +68 -0
- data/test/action_controller/json_api/linked_test.rb +204 -0
- data/test/action_controller/json_api/pagination_test.rb +126 -0
- data/test/action_controller/json_api/transform_test.rb +191 -0
- data/test/action_controller/lookup_proc_test.rb +51 -0
- data/test/action_controller/namespace_lookup_test.rb +239 -0
- data/test/action_controller/serialization_scope_name_test.rb +237 -0
- data/test/action_controller/serialization_test.rb +480 -0
- data/test/active_model_serializers/adapter_for_test.rb +210 -0
- data/test/active_model_serializers/json_pointer_test.rb +24 -0
- data/test/active_model_serializers/logging_test.rb +79 -0
- data/test/active_model_serializers/model_test.rb +144 -0
- data/test/active_model_serializers/railtie_test_isolated.rb +70 -0
- data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +163 -0
- data/test/active_model_serializers/serialization_context_test_isolated.rb +73 -0
- data/test/active_model_serializers/test/schema_test.rb +133 -0
- data/test/active_model_serializers/test/serializer_test.rb +64 -0
- data/test/active_record_test.rb +11 -0
- data/test/adapter/attributes_test.rb +42 -0
- data/test/adapter/deprecation_test.rb +102 -0
- data/test/adapter/json/belongs_to_test.rb +47 -0
- data/test/adapter/json/collection_test.rb +106 -0
- data/test/adapter/json/has_many_test.rb +55 -0
- data/test/adapter/json/transform_test.rb +95 -0
- data/test/adapter/json_api/belongs_to_test.rb +157 -0
- data/test/adapter/json_api/collection_test.rb +98 -0
- data/test/adapter/json_api/errors_test.rb +78 -0
- data/test/adapter/json_api/fields_test.rb +98 -0
- data/test/adapter/json_api/has_many_explicit_serializer_test.rb +98 -0
- data/test/adapter/json_api/has_many_test.rb +175 -0
- data/test/adapter/json_api/has_one_test.rb +82 -0
- data/test/adapter/json_api/include_data_if_sideloaded_test.rb +215 -0
- data/test/adapter/json_api/json_api_test.rb +35 -0
- data/test/adapter/json_api/linked_test.rb +415 -0
- data/test/adapter/json_api/links_test.rb +112 -0
- data/test/adapter/json_api/pagination_links_test.rb +208 -0
- data/test/adapter/json_api/parse_test.rb +139 -0
- data/test/adapter/json_api/relationship_test.rb +399 -0
- data/test/adapter/json_api/resource_meta_test.rb +102 -0
- data/test/adapter/json_api/toplevel_jsonapi_test.rb +84 -0
- data/test/adapter/json_api/transform_test.rb +514 -0
- data/test/adapter/json_api/type_test.rb +195 -0
- data/test/adapter/json_test.rb +48 -0
- data/test/adapter/null_test.rb +24 -0
- data/test/adapter/polymorphic_test.rb +220 -0
- data/test/adapter_test.rb +69 -0
- data/test/array_serializer_test.rb +24 -0
- data/test/benchmark/app.rb +67 -0
- data/test/benchmark/benchmarking_support.rb +69 -0
- data/test/benchmark/bm_active_record.rb +83 -0
- data/test/benchmark/bm_adapter.rb +40 -0
- data/test/benchmark/bm_caching.rb +121 -0
- data/test/benchmark/bm_lookup_chain.rb +85 -0
- data/test/benchmark/bm_transform.rb +47 -0
- data/test/benchmark/config.ru +3 -0
- data/test/benchmark/controllers.rb +85 -0
- data/test/benchmark/fixtures.rb +221 -0
- data/test/cache_test.rb +717 -0
- data/test/collection_serializer_test.rb +129 -0
- data/test/fixtures/active_record.rb +115 -0
- data/test/fixtures/poro.rb +227 -0
- data/test/generators/scaffold_controller_generator_test.rb +26 -0
- data/test/generators/serializer_generator_test.rb +77 -0
- data/test/grape_test.rb +198 -0
- data/test/lint_test.rb +51 -0
- data/test/logger_test.rb +22 -0
- data/test/poro_test.rb +11 -0
- data/test/serializable_resource_test.rb +81 -0
- data/test/serializers/association_macros_test.rb +39 -0
- data/test/serializers/associations_test.rb +520 -0
- data/test/serializers/attribute_test.rb +155 -0
- data/test/serializers/attributes_test.rb +54 -0
- data/test/serializers/caching_configuration_test_isolated.rb +172 -0
- data/test/serializers/configuration_test.rb +34 -0
- data/test/serializers/fieldset_test.rb +16 -0
- data/test/serializers/meta_test.rb +204 -0
- data/test/serializers/options_test.rb +34 -0
- data/test/serializers/read_attribute_for_serialization_test.rb +81 -0
- data/test/serializers/reflection_test.rb +481 -0
- data/test/serializers/root_test.rb +23 -0
- data/test/serializers/serialization_test.rb +57 -0
- data/test/serializers/serializer_for_test.rb +138 -0
- data/test/serializers/serializer_for_with_namespace_test.rb +90 -0
- data/test/support/custom_schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
- data/test/support/isolated_unit.rb +86 -0
- data/test/support/rails5_shims.rb +55 -0
- data/test/support/rails_app.rb +40 -0
- data/test/support/schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
- data/test/support/schemas/active_model_serializers/test/schema_test/my/show.json +6 -0
- data/test/support/schemas/custom/show.json +7 -0
- data/test/support/schemas/hyper_schema.json +93 -0
- data/test/support/schemas/render_using_json_api.json +43 -0
- data/test/support/schemas/simple_json_pointers.json +10 -0
- data/test/support/serialization_testing.rb +81 -0
- data/test/test_helper.rb +72 -0
- metadata +622 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
|
|
5
|
+
module ActiveModel
|
|
6
|
+
class Serializer
|
|
7
|
+
class OptionsTest < ActiveSupport::TestCase
|
|
8
|
+
class ModelWithOptions < ActiveModelSerializers::Model
|
|
9
|
+
attributes :name, :description
|
|
10
|
+
end
|
|
11
|
+
class ModelWithOptionsSerializer < ActiveModel::Serializer
|
|
12
|
+
attributes :name, :description
|
|
13
|
+
|
|
14
|
+
def arguments_passed_in?
|
|
15
|
+
instance_options[:my_options] == :accessible
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
setup do
|
|
20
|
+
@model_with_options = ModelWithOptions.new(name: 'Name 1', description: 'Description 1')
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def test_options_are_accessible
|
|
24
|
+
model_with_options_serializer = ModelWithOptionsSerializer.new(@model_with_options, my_options: :accessible)
|
|
25
|
+
assert model_with_options_serializer.arguments_passed_in?
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def test_no_option_is_passed_in
|
|
29
|
+
model_with_options_serializer = ModelWithOptionsSerializer.new(@model_with_options)
|
|
30
|
+
refute model_with_options_serializer.arguments_passed_in?
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
|
|
5
|
+
module ActiveModel
|
|
6
|
+
class Serializer
|
|
7
|
+
class ReadAttributeForSerializationTest < ActiveSupport::TestCase
|
|
8
|
+
# https://github.com/rails-api/active_model_serializers/issues/1653
|
|
9
|
+
class Parent < ActiveModelSerializers::Model
|
|
10
|
+
attributes :id
|
|
11
|
+
end
|
|
12
|
+
class Child < Parent
|
|
13
|
+
attributes :name
|
|
14
|
+
end
|
|
15
|
+
class ParentSerializer < ActiveModel::Serializer
|
|
16
|
+
attributes :$id
|
|
17
|
+
|
|
18
|
+
define_method(:$id) do
|
|
19
|
+
object.id
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
class ChildSerializer < ParentSerializer
|
|
23
|
+
attributes :name
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def test_child_serializer_calls_dynamic_method_in_parent_serializer
|
|
27
|
+
parent = ParentSerializer.new(Parent.new(id: 5))
|
|
28
|
+
child = ChildSerializer.new(Child.new(id: 6, name: 'Child'))
|
|
29
|
+
assert_equal 5, parent.read_attribute_for_serialization(:$id)
|
|
30
|
+
assert_equal 6, child.read_attribute_for_serialization(:$id)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# https://github.com/rails-api/active_model_serializers/issues/1658
|
|
34
|
+
class ErrorResponse < ActiveModelSerializers::Model
|
|
35
|
+
attributes :error
|
|
36
|
+
end
|
|
37
|
+
class ApplicationSerializer < ActiveModel::Serializer
|
|
38
|
+
attributes :status
|
|
39
|
+
|
|
40
|
+
def status
|
|
41
|
+
object.try(:errors).blank? && object.try(:error).blank?
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
class ErrorResponseSerializer < ApplicationSerializer
|
|
45
|
+
attributes :error
|
|
46
|
+
end
|
|
47
|
+
class ErrorResponseWithSuperSerializer < ApplicationSerializer
|
|
48
|
+
attributes :error
|
|
49
|
+
|
|
50
|
+
def success
|
|
51
|
+
super
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def test_child_serializer_with_error_attribute
|
|
56
|
+
error = ErrorResponse.new(error: 'i have an error')
|
|
57
|
+
serializer = ErrorResponseSerializer.new(error)
|
|
58
|
+
serializer_with_super = ErrorResponseWithSuperSerializer.new(error)
|
|
59
|
+
assert_equal false, serializer.read_attribute_for_serialization(:status)
|
|
60
|
+
assert_equal false, serializer_with_super.read_attribute_for_serialization(:status)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def test_child_serializer_with_errors
|
|
64
|
+
error = ErrorResponse.new
|
|
65
|
+
error.errors.add(:invalid, 'i am not valid')
|
|
66
|
+
serializer = ErrorResponseSerializer.new(error)
|
|
67
|
+
serializer_with_super = ErrorResponseWithSuperSerializer.new(error)
|
|
68
|
+
assert_equal false, serializer.read_attribute_for_serialization(:status)
|
|
69
|
+
assert_equal false, serializer_with_super.read_attribute_for_serialization(:status)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def test_child_serializer_no_error_attribute_or_errors
|
|
73
|
+
error = ErrorResponse.new
|
|
74
|
+
serializer = ErrorResponseSerializer.new(error)
|
|
75
|
+
serializer_with_super = ErrorResponseWithSuperSerializer.new(error)
|
|
76
|
+
assert_equal true, serializer.read_attribute_for_serialization(:status)
|
|
77
|
+
assert_equal true, serializer_with_super.read_attribute_for_serialization(:status)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
module ActiveModel
|
|
5
|
+
class Serializer
|
|
6
|
+
class ReflectionTest < ActiveSupport::TestCase
|
|
7
|
+
class Blog < ActiveModelSerializers::Model
|
|
8
|
+
attributes :id
|
|
9
|
+
end
|
|
10
|
+
class BlogSerializer < ActiveModel::Serializer
|
|
11
|
+
type 'blog'
|
|
12
|
+
attributes :id
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
setup do
|
|
16
|
+
@expected_meta = { id: 1 }
|
|
17
|
+
@expected_links = { self: 'no_uri_validation' }
|
|
18
|
+
@empty_links = {}
|
|
19
|
+
model_attributes = { blog: Blog.new(@expected_meta) }
|
|
20
|
+
@model = Class.new(ActiveModelSerializers::Model) do
|
|
21
|
+
attributes(*model_attributes.keys)
|
|
22
|
+
|
|
23
|
+
def self.name
|
|
24
|
+
'TestModel'
|
|
25
|
+
end
|
|
26
|
+
end.new(model_attributes)
|
|
27
|
+
@instance_options = {}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def evaluate_association_value(association)
|
|
31
|
+
association.lazy_association.eval_reflection_block
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# TODO: Remaining tests
|
|
35
|
+
# test_reflection_value_block_with_scope
|
|
36
|
+
# test_reflection_value_uses_serializer_instance_method
|
|
37
|
+
# test_reflection_excluded_eh_blank_is_false
|
|
38
|
+
# test_reflection_excluded_eh_if
|
|
39
|
+
# test_reflection_excluded_eh_unless
|
|
40
|
+
# test_evaluate_condition_symbol_serializer_method
|
|
41
|
+
# test_evaluate_condition_string_serializer_method
|
|
42
|
+
# test_evaluate_condition_proc
|
|
43
|
+
# test_evaluate_condition_proc_yields_serializer
|
|
44
|
+
# test_evaluate_condition_other
|
|
45
|
+
# test_options_key
|
|
46
|
+
# test_options_polymorphic
|
|
47
|
+
# test_options_serializer
|
|
48
|
+
# test_options_virtual_value
|
|
49
|
+
# test_options_namespace
|
|
50
|
+
|
|
51
|
+
def test_reflection_value
|
|
52
|
+
serializer_class = Class.new(ActiveModel::Serializer) do
|
|
53
|
+
has_one :blog
|
|
54
|
+
end
|
|
55
|
+
serializer_instance = serializer_class.new(@model, @instance_options)
|
|
56
|
+
|
|
57
|
+
# Get Reflection
|
|
58
|
+
reflection = serializer_class._reflections.fetch(:blog)
|
|
59
|
+
|
|
60
|
+
# Assert
|
|
61
|
+
assert_nil reflection.block
|
|
62
|
+
assert_equal Serializer.config.include_data_default, reflection.options.fetch(:include_data_setting)
|
|
63
|
+
assert_equal true, reflection.options.fetch(:include_data_setting)
|
|
64
|
+
|
|
65
|
+
include_slice = :does_not_matter
|
|
66
|
+
assert_equal @model.blog, reflection.send(:value, serializer_instance, include_slice)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def test_reflection_value_block
|
|
70
|
+
serializer_class = Class.new(ActiveModel::Serializer) do
|
|
71
|
+
has_one :blog do
|
|
72
|
+
object.blog
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
serializer_instance = serializer_class.new(@model, @instance_options)
|
|
76
|
+
|
|
77
|
+
# Get Reflection
|
|
78
|
+
reflection = serializer_class._reflections.fetch(:blog)
|
|
79
|
+
|
|
80
|
+
# Assert
|
|
81
|
+
assert_respond_to reflection.block, :call
|
|
82
|
+
assert_equal Serializer.config.include_data_default, reflection.options.fetch(:include_data_setting)
|
|
83
|
+
assert_equal true, reflection.options.fetch(:include_data_setting)
|
|
84
|
+
|
|
85
|
+
include_slice = :does_not_matter
|
|
86
|
+
assert_equal @model.blog, reflection.send(:value, serializer_instance, include_slice)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def test_reflection_value_block_with_explicit_include_data_true
|
|
90
|
+
serializer_class = Class.new(ActiveModel::Serializer) do
|
|
91
|
+
has_one :blog do
|
|
92
|
+
include_data true
|
|
93
|
+
object.blog
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
serializer_instance = serializer_class.new(@model, @instance_options)
|
|
97
|
+
|
|
98
|
+
# Get Reflection
|
|
99
|
+
reflection = serializer_class._reflections.fetch(:blog)
|
|
100
|
+
|
|
101
|
+
# Assert
|
|
102
|
+
assert_respond_to reflection.block, :call
|
|
103
|
+
assert_equal Serializer.config.include_data_default, reflection.options.fetch(:include_data_setting)
|
|
104
|
+
assert_equal true, reflection.options.fetch(:include_data_setting)
|
|
105
|
+
|
|
106
|
+
include_slice = :does_not_matter
|
|
107
|
+
assert_equal @model.blog, reflection.send(:value, serializer_instance, include_slice)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def test_reflection_value_block_with_include_data_false_mutates_the_reflection_include_data
|
|
111
|
+
serializer_class = Class.new(ActiveModel::Serializer) do
|
|
112
|
+
has_one :blog do
|
|
113
|
+
include_data false
|
|
114
|
+
object.blog
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
serializer_instance = serializer_class.new(@model, @instance_options)
|
|
118
|
+
|
|
119
|
+
# Get Reflection
|
|
120
|
+
reflection = serializer_class._reflections.fetch(:blog)
|
|
121
|
+
|
|
122
|
+
# Assert
|
|
123
|
+
assert_respond_to reflection.block, :call
|
|
124
|
+
assert_equal true, reflection.options.fetch(:include_data_setting)
|
|
125
|
+
include_slice = :does_not_matter
|
|
126
|
+
assert_nil reflection.send(:value, serializer_instance, include_slice)
|
|
127
|
+
assert_equal false, reflection.options.fetch(:include_data_setting)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def test_reflection_value_block_with_include_data_if_sideloaded_included_mutates_the_reflection_include_data
|
|
131
|
+
serializer_class = Class.new(ActiveModel::Serializer) do
|
|
132
|
+
has_one :blog do
|
|
133
|
+
include_data :if_sideloaded
|
|
134
|
+
object.blog
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
serializer_instance = serializer_class.new(@model, @instance_options)
|
|
138
|
+
|
|
139
|
+
# Get Reflection
|
|
140
|
+
reflection = serializer_class._reflections.fetch(:blog)
|
|
141
|
+
|
|
142
|
+
# Assert
|
|
143
|
+
assert_respond_to reflection.block, :call
|
|
144
|
+
assert_equal true, reflection.options.fetch(:include_data_setting)
|
|
145
|
+
include_slice = {}
|
|
146
|
+
assert_nil reflection.send(:value, serializer_instance, include_slice)
|
|
147
|
+
assert_equal :if_sideloaded, reflection.options.fetch(:include_data_setting)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def test_reflection_value_block_with_include_data_if_sideloaded_excluded_mutates_the_reflection_include_data
|
|
151
|
+
serializer_class = Class.new(ActiveModel::Serializer) do
|
|
152
|
+
has_one :blog do
|
|
153
|
+
include_data :if_sideloaded
|
|
154
|
+
object.blog
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
serializer_instance = serializer_class.new(@model, @instance_options)
|
|
158
|
+
|
|
159
|
+
# Get Reflection
|
|
160
|
+
reflection = serializer_class._reflections.fetch(:blog)
|
|
161
|
+
|
|
162
|
+
# Assert
|
|
163
|
+
assert_respond_to reflection.block, :call
|
|
164
|
+
assert_equal true, reflection.options.fetch(:include_data_setting)
|
|
165
|
+
include_slice = { blog: :does_not_matter }
|
|
166
|
+
assert_equal @model.blog, reflection.send(:value, serializer_instance, include_slice)
|
|
167
|
+
assert_equal :if_sideloaded, reflection.options.fetch(:include_data_setting)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def test_reflection_block_with_link_mutates_the_reflection_links
|
|
171
|
+
serializer_class = Class.new(ActiveModel::Serializer) do
|
|
172
|
+
has_one :blog do
|
|
173
|
+
link :self, 'no_uri_validation'
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
serializer_instance = serializer_class.new(@model, @instance_options)
|
|
177
|
+
|
|
178
|
+
# Get Reflection
|
|
179
|
+
reflection = serializer_class._reflections.fetch(:blog)
|
|
180
|
+
assert_equal @empty_links, reflection.options.fetch(:links)
|
|
181
|
+
|
|
182
|
+
# Build Association
|
|
183
|
+
association = reflection.build_association(serializer_instance, @instance_options)
|
|
184
|
+
|
|
185
|
+
# Assert association links empty when not yet evaluated
|
|
186
|
+
assert_equal @empty_links, reflection.options.fetch(:links)
|
|
187
|
+
assert_equal @empty_links, association.links
|
|
188
|
+
|
|
189
|
+
evaluate_association_value(association)
|
|
190
|
+
|
|
191
|
+
assert_equal @expected_links, association.links
|
|
192
|
+
assert_equal @expected_links, reflection.options.fetch(:links)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def test_reflection_block_with_link_block_mutates_the_reflection_links
|
|
196
|
+
serializer_class = Class.new(ActiveModel::Serializer) do
|
|
197
|
+
has_one :blog do
|
|
198
|
+
link :self do
|
|
199
|
+
'no_uri_validation'
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
serializer_instance = serializer_class.new(@model, @instance_options)
|
|
204
|
+
|
|
205
|
+
# Get Reflection
|
|
206
|
+
reflection = serializer_class._reflections.fetch(:blog)
|
|
207
|
+
assert_equal @empty_links, reflection.options.fetch(:links)
|
|
208
|
+
|
|
209
|
+
# Build Association
|
|
210
|
+
association = reflection.build_association(serializer_instance, @instance_options)
|
|
211
|
+
|
|
212
|
+
# Assert association links empty when not yet evaluated
|
|
213
|
+
assert_equal @empty_links, association.links
|
|
214
|
+
|
|
215
|
+
evaluate_association_value(association)
|
|
216
|
+
|
|
217
|
+
# Assert before instance_eval link
|
|
218
|
+
link = association.links.fetch(:self)
|
|
219
|
+
assert_respond_to link, :call
|
|
220
|
+
assert_respond_to reflection.options.fetch(:links).fetch(:self), :call
|
|
221
|
+
|
|
222
|
+
# Assert after instance_eval link
|
|
223
|
+
assert_equal @expected_links.fetch(:self), reflection.instance_eval(&link)
|
|
224
|
+
assert_respond_to reflection.options.fetch(:links).fetch(:self), :call
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def test_reflection_block_with_meta_mutates_the_reflection_meta
|
|
228
|
+
serializer_class = Class.new(ActiveModel::Serializer) do
|
|
229
|
+
has_one :blog do
|
|
230
|
+
meta(id: object.blog.id)
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
serializer_instance = serializer_class.new(@model, @instance_options)
|
|
234
|
+
|
|
235
|
+
# Get Reflection
|
|
236
|
+
reflection = serializer_class._reflections.fetch(:blog)
|
|
237
|
+
assert_nil reflection.options.fetch(:meta)
|
|
238
|
+
|
|
239
|
+
# Build Association
|
|
240
|
+
association = reflection.build_association(serializer_instance, @instance_options)
|
|
241
|
+
|
|
242
|
+
evaluate_association_value(association)
|
|
243
|
+
|
|
244
|
+
assert_equal @expected_meta, association.meta
|
|
245
|
+
assert_equal @expected_meta, reflection.options.fetch(:meta)
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def test_reflection_block_with_meta_block_mutates_the_reflection_meta
|
|
249
|
+
serializer_class = Class.new(ActiveModel::Serializer) do
|
|
250
|
+
has_one :blog do
|
|
251
|
+
meta do
|
|
252
|
+
{ id: object.blog.id }
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
serializer_instance = serializer_class.new(@model, @instance_options)
|
|
257
|
+
|
|
258
|
+
# Get Reflection
|
|
259
|
+
reflection = serializer_class._reflections.fetch(:blog)
|
|
260
|
+
assert_nil reflection.options.fetch(:meta)
|
|
261
|
+
|
|
262
|
+
# Build Association
|
|
263
|
+
association = reflection.build_association(serializer_instance, @instance_options)
|
|
264
|
+
# Assert before instance_eval meta
|
|
265
|
+
|
|
266
|
+
evaluate_association_value(association)
|
|
267
|
+
|
|
268
|
+
assert_respond_to association.meta, :call
|
|
269
|
+
assert_respond_to reflection.options.fetch(:meta), :call
|
|
270
|
+
|
|
271
|
+
# Assert after instance_eval meta
|
|
272
|
+
assert_equal @expected_meta, reflection.instance_eval(&association.meta)
|
|
273
|
+
assert_respond_to reflection.options.fetch(:meta), :call
|
|
274
|
+
assert_respond_to association.meta, :call
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
# rubocop:disable Metrics/AbcSize
|
|
278
|
+
def test_reflection_block_with_meta_in_link_block_mutates_the_reflection_meta
|
|
279
|
+
serializer_class = Class.new(ActiveModel::Serializer) do
|
|
280
|
+
has_one :blog do
|
|
281
|
+
link :self do
|
|
282
|
+
meta(id: object.blog.id)
|
|
283
|
+
'no_uri_validation'
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
serializer_instance = serializer_class.new(@model, @instance_options)
|
|
288
|
+
|
|
289
|
+
# Get Reflection
|
|
290
|
+
reflection = serializer_class._reflections.fetch(:blog)
|
|
291
|
+
assert_nil reflection.options.fetch(:meta)
|
|
292
|
+
assert_equal @empty_links, reflection.options.fetch(:links)
|
|
293
|
+
|
|
294
|
+
# Build Association
|
|
295
|
+
association = reflection.build_association(serializer_instance, @instance_options)
|
|
296
|
+
# Assert before instance_eval link meta
|
|
297
|
+
assert_nil association.meta
|
|
298
|
+
assert_nil reflection.options.fetch(:meta)
|
|
299
|
+
|
|
300
|
+
evaluate_association_value(association)
|
|
301
|
+
|
|
302
|
+
link = association.links.fetch(:self)
|
|
303
|
+
assert_respond_to link, :call
|
|
304
|
+
assert_respond_to reflection.options.fetch(:links).fetch(:self), :call
|
|
305
|
+
assert_nil reflection.options.fetch(:meta)
|
|
306
|
+
|
|
307
|
+
# Assert after instance_eval link
|
|
308
|
+
assert_equal 'no_uri_validation', reflection.instance_eval(&link)
|
|
309
|
+
assert_equal @expected_meta, reflection.options.fetch(:meta)
|
|
310
|
+
assert_equal @expected_meta, association.meta
|
|
311
|
+
end
|
|
312
|
+
# rubocop:enable Metrics/AbcSize
|
|
313
|
+
|
|
314
|
+
# rubocop:disable Metrics/AbcSize
|
|
315
|
+
def test_reflection_block_with_meta_block_in_link_block_mutates_the_reflection_meta
|
|
316
|
+
serializer_class = Class.new(ActiveModel::Serializer) do
|
|
317
|
+
has_one :blog do
|
|
318
|
+
link :self do
|
|
319
|
+
meta do
|
|
320
|
+
{ id: object.blog.id }
|
|
321
|
+
end
|
|
322
|
+
'no_uri_validation'
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
end
|
|
326
|
+
serializer_instance = serializer_class.new(@model, @instance_options)
|
|
327
|
+
|
|
328
|
+
# Get Reflection
|
|
329
|
+
reflection = serializer_class._reflections.fetch(:blog)
|
|
330
|
+
assert_nil reflection.options.fetch(:meta)
|
|
331
|
+
|
|
332
|
+
# Build Association
|
|
333
|
+
association = reflection.build_association(serializer_instance, @instance_options)
|
|
334
|
+
assert_nil association.meta
|
|
335
|
+
assert_nil reflection.options.fetch(:meta)
|
|
336
|
+
|
|
337
|
+
# Assert before instance_eval link
|
|
338
|
+
|
|
339
|
+
evaluate_association_value(association)
|
|
340
|
+
|
|
341
|
+
link = association.links.fetch(:self)
|
|
342
|
+
assert_nil reflection.options.fetch(:meta)
|
|
343
|
+
assert_respond_to link, :call
|
|
344
|
+
assert_respond_to association.links.fetch(:self), :call
|
|
345
|
+
|
|
346
|
+
# Assert after instance_eval link
|
|
347
|
+
assert_equal 'no_uri_validation', reflection.instance_eval(&link)
|
|
348
|
+
assert_respond_to association.links.fetch(:self), :call
|
|
349
|
+
# Assert before instance_eval link meta
|
|
350
|
+
assert_respond_to reflection.options.fetch(:meta), :call
|
|
351
|
+
assert_respond_to association.meta, :call
|
|
352
|
+
|
|
353
|
+
# Assert after instance_eval link meta
|
|
354
|
+
assert_equal @expected_meta, reflection.instance_eval(&reflection.options.fetch(:meta))
|
|
355
|
+
assert_respond_to association.meta, :call
|
|
356
|
+
end
|
|
357
|
+
# rubocop:enable Metrics/AbcSize
|
|
358
|
+
|
|
359
|
+
def test_no_href_in_vanilla_reflection
|
|
360
|
+
serializer_class = Class.new(ActiveModel::Serializer) do
|
|
361
|
+
has_one :blog do
|
|
362
|
+
link :self do
|
|
363
|
+
href 'no_uri_validation'
|
|
364
|
+
end
|
|
365
|
+
end
|
|
366
|
+
end
|
|
367
|
+
serializer_instance = serializer_class.new(@model, @instance_options)
|
|
368
|
+
|
|
369
|
+
# Get Reflection
|
|
370
|
+
reflection = serializer_class._reflections.fetch(:blog)
|
|
371
|
+
assert_equal @empty_links, reflection.options.fetch(:links)
|
|
372
|
+
|
|
373
|
+
# Build Association
|
|
374
|
+
association = reflection.build_association(serializer_instance, @instance_options)
|
|
375
|
+
# Assert before instance_eval link
|
|
376
|
+
|
|
377
|
+
evaluate_association_value(association)
|
|
378
|
+
|
|
379
|
+
link = association.links.fetch(:self)
|
|
380
|
+
assert_respond_to link, :call
|
|
381
|
+
|
|
382
|
+
# Assert after instance_eval link
|
|
383
|
+
exception = assert_raise(NoMethodError) do
|
|
384
|
+
reflection.instance_eval(&link)
|
|
385
|
+
end
|
|
386
|
+
assert_match(/undefined method `href'/, exception.message)
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
# rubocop:disable Metrics/AbcSize
|
|
390
|
+
def test_mutating_reflection_block_is_not_thread_safe
|
|
391
|
+
serializer_class = Class.new(ActiveModel::Serializer) do
|
|
392
|
+
has_one :blog do
|
|
393
|
+
meta(id: object.blog.id)
|
|
394
|
+
end
|
|
395
|
+
end
|
|
396
|
+
model1_meta = @expected_meta
|
|
397
|
+
# Evaluate reflection meta for model with id 1
|
|
398
|
+
serializer_instance = serializer_class.new(@model, @instance_options)
|
|
399
|
+
reflection = serializer_class._reflections.fetch(:blog)
|
|
400
|
+
assert_nil reflection.options.fetch(:meta)
|
|
401
|
+
association = reflection.build_association(serializer_instance, @instance_options)
|
|
402
|
+
|
|
403
|
+
evaluate_association_value(association)
|
|
404
|
+
|
|
405
|
+
assert_equal model1_meta, association.meta
|
|
406
|
+
assert_equal model1_meta, reflection.options.fetch(:meta)
|
|
407
|
+
|
|
408
|
+
model2_meta = @expected_meta.merge(id: 2)
|
|
409
|
+
# Evaluate reflection meta for model with id 2
|
|
410
|
+
@model.blog.id = 2
|
|
411
|
+
assert_equal 2, @model.blog.id # sanity check
|
|
412
|
+
serializer_instance = serializer_class.new(@model, @instance_options)
|
|
413
|
+
reflection = serializer_class._reflections.fetch(:blog)
|
|
414
|
+
|
|
415
|
+
# WARN: Thread-safety issue
|
|
416
|
+
# Before the reflection is evaluated, it has the value from the previous evaluation
|
|
417
|
+
assert_equal model1_meta, reflection.options.fetch(:meta)
|
|
418
|
+
|
|
419
|
+
association = reflection.build_association(serializer_instance, @instance_options)
|
|
420
|
+
|
|
421
|
+
evaluate_association_value(association)
|
|
422
|
+
|
|
423
|
+
assert_equal model2_meta, association.meta
|
|
424
|
+
assert_equal model2_meta, reflection.options.fetch(:meta)
|
|
425
|
+
end
|
|
426
|
+
# rubocop:enable Metrics/AbcSize
|
|
427
|
+
end
|
|
428
|
+
class ThreadedReflectionTest < ActiveSupport::TestCase
|
|
429
|
+
class Post < ::Model
|
|
430
|
+
attributes :id, :title, :body
|
|
431
|
+
associations :comments
|
|
432
|
+
end
|
|
433
|
+
class Comment < ::Model
|
|
434
|
+
attributes :id, :body
|
|
435
|
+
associations :post
|
|
436
|
+
end
|
|
437
|
+
class CommentSerializer < ActiveModel::Serializer
|
|
438
|
+
type 'comment'
|
|
439
|
+
attributes :id, :body
|
|
440
|
+
has_one :post
|
|
441
|
+
end
|
|
442
|
+
class PostSerializer < ActiveModel::Serializer
|
|
443
|
+
type 'post'
|
|
444
|
+
attributes :id, :title, :body
|
|
445
|
+
has_many :comments, serializer: CommentSerializer do
|
|
446
|
+
sleep 0.1
|
|
447
|
+
object.comments
|
|
448
|
+
end
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
# per https://github.com/rails-api/active_model_serializers/issues/2270
|
|
452
|
+
def test_concurrent_serialization
|
|
453
|
+
post1 = Post.new(id: 1, title: 'Post 1 Title', body: 'Post 1 Body')
|
|
454
|
+
post1.comments = [Comment.new(id: 1, body: 'Comment on Post 1', post: post1)]
|
|
455
|
+
post2 = Post.new(id: 2, title: 'Post 2 Title', body: 'Post 2 Body')
|
|
456
|
+
post2.comments = [Comment.new(id: 2, body: 'Comment on Post 2', post: post2)]
|
|
457
|
+
serialized_posts = {
|
|
458
|
+
first: Set.new,
|
|
459
|
+
second: Set.new
|
|
460
|
+
}
|
|
461
|
+
t1 = Thread.new do
|
|
462
|
+
10.times do
|
|
463
|
+
serialized_posts[:first] << PostSerializer.new(post1, {}).to_json
|
|
464
|
+
end
|
|
465
|
+
end
|
|
466
|
+
t2 = Thread.new do
|
|
467
|
+
10.times do
|
|
468
|
+
serialized_posts[:second] << PostSerializer.new(post2, {}).to_json
|
|
469
|
+
end
|
|
470
|
+
end
|
|
471
|
+
t1.join
|
|
472
|
+
t2.join
|
|
473
|
+
expected_first_post_serialization = '{"id":1,"title":"Post 1 Title","body":"Post 1 Body","comments":[{"id":1,"body":"Comment on Post 1"}]}'
|
|
474
|
+
expected_second_post_serialization = '{"id":2,"title":"Post 2 Title","body":"Post 2 Body","comments":[{"id":2,"body":"Comment on Post 2"}]}'
|
|
475
|
+
|
|
476
|
+
assert_equal [expected_second_post_serialization], serialized_posts[:second].to_a
|
|
477
|
+
assert_equal [expected_first_post_serialization], serialized_posts[:first].to_a
|
|
478
|
+
end
|
|
479
|
+
end
|
|
480
|
+
end
|
|
481
|
+
end
|