agi_active_model_serializers 0.10.7
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 +102 -0
- data/.simplecov +110 -0
- data/.travis.yml +51 -0
- data/CHANGELOG.md +612 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/CONTRIBUTING.md +105 -0
- data/Gemfile +56 -0
- data/MIT-LICENSE +22 -0
- data/README.md +307 -0
- data/Rakefile +103 -0
- data/active_model_serializers.gemspec +63 -0
- data/appveyor.yml +24 -0
- data/bin/bench +171 -0
- data/bin/bench_regression +316 -0
- data/bin/serve_benchmark +39 -0
- data/docs/README.md +41 -0
- data/docs/STYLE.md +58 -0
- data/docs/general/adapters.md +247 -0
- data/docs/general/caching.md +58 -0
- data/docs/general/configuration_options.md +169 -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 +14 -0
- data/docs/general/rendering.md +279 -0
- data/docs/general/serializers.md +461 -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 +137 -0
- data/docs/howto/add_root_key.md +55 -0
- data/docs/howto/grape_integration.md +42 -0
- data/docs/howto/outside_controller_use.md +65 -0
- data/docs/howto/passing_arbitrary_options.md +27 -0
- data/docs/howto/serialize_poro.md +32 -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 +144 -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 +66 -0
- data/lib/active_model/serializable_resource.rb +11 -0
- data/lib/active_model/serializer.rb +231 -0
- data/lib/active_model/serializer/adapter.rb +24 -0
- data/lib/active_model/serializer/adapter/attributes.rb +15 -0
- data/lib/active_model/serializer/adapter/base.rb +18 -0
- data/lib/active_model/serializer/adapter/json.rb +15 -0
- data/lib/active_model/serializer/adapter/json_api.rb +15 -0
- data/lib/active_model/serializer/adapter/null.rb +15 -0
- data/lib/active_model/serializer/array_serializer.rb +12 -0
- data/lib/active_model/serializer/association.rb +34 -0
- data/lib/active_model/serializer/attribute.rb +25 -0
- data/lib/active_model/serializer/belongs_to_reflection.rb +7 -0
- data/lib/active_model/serializer/collection_reflection.rb +7 -0
- data/lib/active_model/serializer/collection_serializer.rb +87 -0
- data/lib/active_model/serializer/concerns/associations.rb +102 -0
- data/lib/active_model/serializer/concerns/attributes.rb +82 -0
- data/lib/active_model/serializer/concerns/caching.rb +292 -0
- data/lib/active_model/serializer/concerns/configuration.rb +59 -0
- data/lib/active_model/serializer/concerns/links.rb +35 -0
- data/lib/active_model/serializer/concerns/meta.rb +29 -0
- data/lib/active_model/serializer/concerns/type.rb +25 -0
- data/lib/active_model/serializer/error_serializer.rb +14 -0
- data/lib/active_model/serializer/errors_serializer.rb +32 -0
- data/lib/active_model/serializer/field.rb +90 -0
- data/lib/active_model/serializer/fieldset.rb +31 -0
- data/lib/active_model/serializer/has_many_reflection.rb +7 -0
- data/lib/active_model/serializer/has_one_reflection.rb +7 -0
- data/lib/active_model/serializer/lint.rb +150 -0
- data/lib/active_model/serializer/null.rb +17 -0
- data/lib/active_model/serializer/reflection.rb +163 -0
- data/lib/active_model/serializer/singular_reflection.rb +7 -0
- data/lib/active_model/serializer/version.rb +5 -0
- data/lib/active_model_serializers.rb +53 -0
- data/lib/active_model_serializers/adapter.rb +98 -0
- data/lib/active_model_serializers/adapter/attributes.rb +13 -0
- data/lib/active_model_serializers/adapter/base.rb +83 -0
- data/lib/active_model_serializers/adapter/json.rb +21 -0
- data/lib/active_model_serializers/adapter/json_api.rb +517 -0
- data/lib/active_model_serializers/adapter/json_api/deserialization.rb +213 -0
- data/lib/active_model_serializers/adapter/json_api/error.rb +96 -0
- data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +49 -0
- data/lib/active_model_serializers/adapter/json_api/link.rb +83 -0
- data/lib/active_model_serializers/adapter/json_api/meta.rb +37 -0
- data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +69 -0
- data/lib/active_model_serializers/adapter/json_api/relationship.rb +63 -0
- data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +51 -0
- data/lib/active_model_serializers/adapter/null.rb +9 -0
- data/lib/active_model_serializers/callbacks.rb +55 -0
- data/lib/active_model_serializers/deprecate.rb +54 -0
- data/lib/active_model_serializers/deserialization.rb +15 -0
- data/lib/active_model_serializers/json_pointer.rb +14 -0
- data/lib/active_model_serializers/logging.rb +122 -0
- data/lib/active_model_serializers/lookup_chain.rb +80 -0
- data/lib/active_model_serializers/model.rb +71 -0
- data/lib/active_model_serializers/railtie.rb +48 -0
- data/lib/active_model_serializers/register_jsonapi_renderer.rb +78 -0
- data/lib/active_model_serializers/serializable_resource.rb +82 -0
- data/lib/active_model_serializers/serialization_context.rb +39 -0
- data/lib/active_model_serializers/test.rb +7 -0
- data/lib/active_model_serializers/test/schema.rb +138 -0
- data/lib/active_model_serializers/test/serializer.rb +125 -0
- data/lib/generators/rails/USAGE +6 -0
- data/lib/generators/rails/resource_override.rb +10 -0
- data/lib/generators/rails/serializer_generator.rb +36 -0
- data/lib/generators/rails/templates/serializer.rb.erb +15 -0
- data/lib/grape/active_model_serializers.rb +16 -0
- data/lib/grape/formatters/active_model_serializers.rb +32 -0
- data/lib/grape/helpers/active_model_serializers.rb +17 -0
- data/test/action_controller/adapter_selector_test.rb +53 -0
- data/test/action_controller/explicit_serializer_test.rb +135 -0
- data/test/action_controller/json/include_test.rb +246 -0
- data/test/action_controller/json_api/deserialization_test.rb +112 -0
- data/test/action_controller/json_api/errors_test.rb +40 -0
- data/test/action_controller/json_api/fields_test.rb +66 -0
- data/test/action_controller/json_api/linked_test.rb +202 -0
- data/test/action_controller/json_api/pagination_test.rb +116 -0
- data/test/action_controller/json_api/transform_test.rb +189 -0
- data/test/action_controller/lookup_proc_test.rb +49 -0
- data/test/action_controller/namespace_lookup_test.rb +232 -0
- data/test/action_controller/serialization_scope_name_test.rb +229 -0
- data/test/action_controller/serialization_test.rb +472 -0
- data/test/active_model_serializers/adapter_for_test.rb +208 -0
- data/test/active_model_serializers/json_pointer_test.rb +22 -0
- data/test/active_model_serializers/logging_test.rb +77 -0
- data/test/active_model_serializers/model_test.rb +69 -0
- data/test/active_model_serializers/railtie_test_isolated.rb +63 -0
- data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +161 -0
- data/test/active_model_serializers/serialization_context_test_isolated.rb +71 -0
- data/test/active_model_serializers/test/schema_test.rb +131 -0
- data/test/active_model_serializers/test/serializer_test.rb +62 -0
- data/test/active_record_test.rb +9 -0
- data/test/adapter/attributes_test.rb +43 -0
- data/test/adapter/deprecation_test.rb +100 -0
- data/test/adapter/json/belongs_to_test.rb +45 -0
- data/test/adapter/json/collection_test.rb +104 -0
- data/test/adapter/json/has_many_test.rb +45 -0
- data/test/adapter/json/transform_test.rb +93 -0
- data/test/adapter/json_api/belongs_to_test.rb +155 -0
- data/test/adapter/json_api/collection_test.rb +96 -0
- data/test/adapter/json_api/errors_test.rb +76 -0
- data/test/adapter/json_api/fields_test.rb +96 -0
- data/test/adapter/json_api/has_many_embed_ids_test.rb +43 -0
- data/test/adapter/json_api/has_many_explicit_serializer_test.rb +96 -0
- data/test/adapter/json_api/has_many_test.rb +165 -0
- data/test/adapter/json_api/has_one_test.rb +80 -0
- data/test/adapter/json_api/include_data_if_sideloaded_test.rb +168 -0
- data/test/adapter/json_api/json_api_test.rb +33 -0
- data/test/adapter/json_api/linked_test.rb +413 -0
- data/test/adapter/json_api/links_test.rb +95 -0
- data/test/adapter/json_api/pagination_links_test.rb +193 -0
- data/test/adapter/json_api/parse_test.rb +137 -0
- data/test/adapter/json_api/relationship_test.rb +397 -0
- data/test/adapter/json_api/resource_identifier_test.rb +110 -0
- data/test/adapter/json_api/resource_meta_test.rb +100 -0
- data/test/adapter/json_api/toplevel_jsonapi_test.rb +82 -0
- data/test/adapter/json_api/transform_test.rb +512 -0
- data/test/adapter/json_api/type_test.rb +61 -0
- data/test/adapter/json_test.rb +46 -0
- data/test/adapter/null_test.rb +22 -0
- data/test/adapter/polymorphic_test.rb +171 -0
- data/test/adapter_test.rb +67 -0
- data/test/array_serializer_test.rb +22 -0
- data/test/benchmark/app.rb +65 -0
- data/test/benchmark/benchmarking_support.rb +67 -0
- data/test/benchmark/bm_active_record.rb +81 -0
- data/test/benchmark/bm_adapter.rb +38 -0
- data/test/benchmark/bm_caching.rb +119 -0
- data/test/benchmark/bm_lookup_chain.rb +83 -0
- data/test/benchmark/bm_transform.rb +45 -0
- data/test/benchmark/config.ru +3 -0
- data/test/benchmark/controllers.rb +83 -0
- data/test/benchmark/fixtures.rb +219 -0
- data/test/cache_test.rb +595 -0
- data/test/collection_serializer_test.rb +123 -0
- data/test/fixtures/active_record.rb +113 -0
- data/test/fixtures/poro.rb +232 -0
- data/test/generators/scaffold_controller_generator_test.rb +24 -0
- data/test/generators/serializer_generator_test.rb +74 -0
- data/test/grape_test.rb +178 -0
- data/test/lint_test.rb +49 -0
- data/test/logger_test.rb +20 -0
- data/test/poro_test.rb +9 -0
- data/test/serializable_resource_test.rb +79 -0
- data/test/serializers/association_macros_test.rb +37 -0
- data/test/serializers/associations_test.rb +383 -0
- data/test/serializers/attribute_test.rb +153 -0
- data/test/serializers/attributes_test.rb +52 -0
- data/test/serializers/caching_configuration_test_isolated.rb +170 -0
- data/test/serializers/configuration_test.rb +32 -0
- data/test/serializers/fieldset_test.rb +14 -0
- data/test/serializers/meta_test.rb +202 -0
- data/test/serializers/options_test.rb +32 -0
- data/test/serializers/read_attribute_for_serialization_test.rb +79 -0
- data/test/serializers/root_test.rb +21 -0
- data/test/serializers/serialization_test.rb +55 -0
- data/test/serializers/serializer_for_test.rb +136 -0
- data/test/serializers/serializer_for_with_namespace_test.rb +88 -0
- data/test/support/custom_schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
- data/test/support/isolated_unit.rb +82 -0
- data/test/support/rails5_shims.rb +53 -0
- data/test/support/rails_app.rb +36 -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 +71 -0
- data/test/test_helper.rb +58 -0
- metadata +602 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module ActiveModel
|
|
2
|
+
class Serializer
|
|
3
|
+
module Adapter
|
|
4
|
+
class Attributes < DelegateClass(ActiveModelSerializers::Adapter::Attributes)
|
|
5
|
+
def initialize(serializer, options = {})
|
|
6
|
+
super(ActiveModelSerializers::Adapter::Attributes.new(serializer, options))
|
|
7
|
+
end
|
|
8
|
+
class << self
|
|
9
|
+
extend ActiveModelSerializers::Deprecate
|
|
10
|
+
deprecate :new, 'ActiveModelSerializers::Adapter::Json.'
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module ActiveModel
|
|
2
|
+
class Serializer
|
|
3
|
+
module Adapter
|
|
4
|
+
class Base < DelegateClass(ActiveModelSerializers::Adapter::Base)
|
|
5
|
+
class << self
|
|
6
|
+
extend ActiveModelSerializers::Deprecate
|
|
7
|
+
deprecate :inherited, 'ActiveModelSerializers::Adapter::Base.'
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# :nocov:
|
|
11
|
+
def initialize(serializer, options = {})
|
|
12
|
+
super(ActiveModelSerializers::Adapter::Base.new(serializer, options))
|
|
13
|
+
end
|
|
14
|
+
# :nocov:
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module ActiveModel
|
|
2
|
+
class Serializer
|
|
3
|
+
module Adapter
|
|
4
|
+
class Json < DelegateClass(ActiveModelSerializers::Adapter::Json)
|
|
5
|
+
def initialize(serializer, options = {})
|
|
6
|
+
super(ActiveModelSerializers::Adapter::Json.new(serializer, options))
|
|
7
|
+
end
|
|
8
|
+
class << self
|
|
9
|
+
extend ActiveModelSerializers::Deprecate
|
|
10
|
+
deprecate :new, 'ActiveModelSerializers::Adapter::Json.new'
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module ActiveModel
|
|
2
|
+
class Serializer
|
|
3
|
+
module Adapter
|
|
4
|
+
class JsonApi < DelegateClass(ActiveModelSerializers::Adapter::JsonApi)
|
|
5
|
+
def initialize(serializer, options = {})
|
|
6
|
+
super(ActiveModelSerializers::Adapter::JsonApi.new(serializer, options))
|
|
7
|
+
end
|
|
8
|
+
class << self
|
|
9
|
+
extend ActiveModelSerializers::Deprecate
|
|
10
|
+
deprecate :new, 'ActiveModelSerializers::Adapter::JsonApi.new'
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module ActiveModel
|
|
2
|
+
class Serializer
|
|
3
|
+
module Adapter
|
|
4
|
+
class Null < DelegateClass(ActiveModelSerializers::Adapter::Null)
|
|
5
|
+
def initialize(serializer, options = {})
|
|
6
|
+
super(ActiveModelSerializers::Adapter::Null.new(serializer, options))
|
|
7
|
+
end
|
|
8
|
+
class << self
|
|
9
|
+
extend ActiveModelSerializers::Deprecate
|
|
10
|
+
deprecate :new, 'ActiveModelSerializers::Adapter::Null.new'
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require 'active_model/serializer/collection_serializer'
|
|
2
|
+
|
|
3
|
+
module ActiveModel
|
|
4
|
+
class Serializer
|
|
5
|
+
class ArraySerializer < CollectionSerializer
|
|
6
|
+
class << self
|
|
7
|
+
extend ActiveModelSerializers::Deprecate
|
|
8
|
+
deprecate :new, 'ActiveModel::Serializer::CollectionSerializer.'
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module ActiveModel
|
|
2
|
+
class Serializer
|
|
3
|
+
# This class holds all information about serializer's association.
|
|
4
|
+
#
|
|
5
|
+
# @attr [Symbol] name
|
|
6
|
+
# @attr [Hash{Symbol => Object}] options
|
|
7
|
+
# @attr [block]
|
|
8
|
+
#
|
|
9
|
+
# @example
|
|
10
|
+
# Association.new(:comments, { serializer: CommentSummarySerializer })
|
|
11
|
+
#
|
|
12
|
+
class Association < Field
|
|
13
|
+
# @return [Symbol]
|
|
14
|
+
def key
|
|
15
|
+
options.fetch(:key, name)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# @return [ActiveModel::Serializer, nil]
|
|
19
|
+
def serializer
|
|
20
|
+
options[:serializer]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# @return [Hash]
|
|
24
|
+
def links
|
|
25
|
+
options.fetch(:links) || {}
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# @return [Hash, nil]
|
|
29
|
+
def meta
|
|
30
|
+
options[:meta]
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'active_model/serializer/field'
|
|
2
|
+
|
|
3
|
+
module ActiveModel
|
|
4
|
+
class Serializer
|
|
5
|
+
# Holds all the meta-data about an attribute as it was specified in the
|
|
6
|
+
# ActiveModel::Serializer class.
|
|
7
|
+
#
|
|
8
|
+
# @example
|
|
9
|
+
# class PostSerializer < ActiveModel::Serializer
|
|
10
|
+
# attribute :content
|
|
11
|
+
# attribute :name, key: :title
|
|
12
|
+
# attribute :email, key: :author_email, if: :user_logged_in?
|
|
13
|
+
# attribute :preview do
|
|
14
|
+
# truncate(object.content)
|
|
15
|
+
# end
|
|
16
|
+
#
|
|
17
|
+
# def user_logged_in?
|
|
18
|
+
# current_user.logged_in?
|
|
19
|
+
# end
|
|
20
|
+
# end
|
|
21
|
+
#
|
|
22
|
+
class Attribute < Field
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
module ActiveModel
|
|
2
|
+
class Serializer
|
|
3
|
+
class CollectionSerializer
|
|
4
|
+
include Enumerable
|
|
5
|
+
delegate :each, to: :@serializers
|
|
6
|
+
|
|
7
|
+
attr_reader :object, :root
|
|
8
|
+
|
|
9
|
+
def initialize(resources, options = {})
|
|
10
|
+
@object = resources
|
|
11
|
+
@options = options
|
|
12
|
+
@root = options[:root]
|
|
13
|
+
@serializers = serializers_from_resources
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def success?
|
|
17
|
+
true
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# @api private
|
|
21
|
+
def serializable_hash(adapter_options, options, adapter_instance)
|
|
22
|
+
include_directive = ActiveModel::Serializer.include_directive_from_options(adapter_options)
|
|
23
|
+
adapter_options[:cached_attributes] ||= ActiveModel::Serializer.cache_read_multi(self, adapter_instance, include_directive)
|
|
24
|
+
adapter_opts = adapter_options.merge(include_directive: include_directive)
|
|
25
|
+
serializers.map do |serializer|
|
|
26
|
+
serializer.serializable_hash(adapter_opts, options, adapter_instance)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# TODO: unify naming of root, json_key, and _type. Right now, a serializer's
|
|
31
|
+
# json_key comes from the root option or the object's model name, by default.
|
|
32
|
+
# But, if a dev defines a custom `json_key` method with an explicit value,
|
|
33
|
+
# we have no simple way to know that it is safe to call that instance method.
|
|
34
|
+
# (which is really a class property at this point, anyhow).
|
|
35
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
|
36
|
+
# Disabling cop since it's good to highlight the complexity of this method by
|
|
37
|
+
# including all the logic right here.
|
|
38
|
+
def json_key
|
|
39
|
+
return root if root
|
|
40
|
+
# 1. get from options[:serializer] for empty resource collection
|
|
41
|
+
key = object.empty? &&
|
|
42
|
+
(explicit_serializer_class = options[:serializer]) &&
|
|
43
|
+
explicit_serializer_class._type
|
|
44
|
+
# 2. get from first serializer instance in collection
|
|
45
|
+
key ||= (serializer = serializers.first) && serializer.json_key
|
|
46
|
+
# 3. get from collection name, if a named collection
|
|
47
|
+
key ||= object.respond_to?(:name) ? object.name && object.name.underscore : nil
|
|
48
|
+
# 4. key may be nil for empty collection and no serializer option
|
|
49
|
+
key && key.pluralize
|
|
50
|
+
end
|
|
51
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
|
52
|
+
|
|
53
|
+
def paginated?
|
|
54
|
+
ActiveModelSerializers.config.jsonapi_pagination_links_enabled &&
|
|
55
|
+
object.respond_to?(:current_page) &&
|
|
56
|
+
object.respond_to?(:total_pages) &&
|
|
57
|
+
object.respond_to?(:size)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
protected
|
|
61
|
+
|
|
62
|
+
attr_reader :serializers, :options
|
|
63
|
+
|
|
64
|
+
private
|
|
65
|
+
|
|
66
|
+
def serializers_from_resources
|
|
67
|
+
serializer_context_class = options.fetch(:serializer_context_class, ActiveModel::Serializer)
|
|
68
|
+
object.map do |resource|
|
|
69
|
+
serializer_from_resource(resource, serializer_context_class, options)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def serializer_from_resource(resource, serializer_context_class, options)
|
|
74
|
+
serializer_class = options.fetch(:serializer) do
|
|
75
|
+
serializer_context_class.serializer_for(resource, namespace: options[:namespace])
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
if serializer_class.nil?
|
|
79
|
+
ActiveModelSerializers.logger.debug "No serializer found for resource: #{resource.inspect}"
|
|
80
|
+
throw :no_serializer
|
|
81
|
+
else
|
|
82
|
+
serializer_class.new(resource, options.except(:serializer))
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
module ActiveModel
|
|
2
|
+
class Serializer
|
|
3
|
+
# Defines an association in the object should be rendered.
|
|
4
|
+
#
|
|
5
|
+
# The serializer object should implement the association name
|
|
6
|
+
# as a method which should return an array when invoked. If a method
|
|
7
|
+
# with the association name does not exist, the association name is
|
|
8
|
+
# dispatched to the serialized object.
|
|
9
|
+
#
|
|
10
|
+
module Associations
|
|
11
|
+
extend ActiveSupport::Concern
|
|
12
|
+
|
|
13
|
+
included do
|
|
14
|
+
with_options instance_writer: false, instance_reader: true do |serializer|
|
|
15
|
+
serializer.class_attribute :_reflections
|
|
16
|
+
self._reflections ||= {}
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
extend ActiveSupport::Autoload
|
|
20
|
+
autoload :Association
|
|
21
|
+
autoload :Reflection
|
|
22
|
+
autoload :SingularReflection
|
|
23
|
+
autoload :CollectionReflection
|
|
24
|
+
autoload :BelongsToReflection
|
|
25
|
+
autoload :HasOneReflection
|
|
26
|
+
autoload :HasManyReflection
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
module ClassMethods
|
|
30
|
+
def inherited(base)
|
|
31
|
+
super
|
|
32
|
+
base._reflections = _reflections.dup
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# @param [Symbol] name of the association
|
|
36
|
+
# @param [Hash<Symbol => any>] options for the reflection
|
|
37
|
+
# @return [void]
|
|
38
|
+
#
|
|
39
|
+
# @example
|
|
40
|
+
# has_many :comments, serializer: CommentSummarySerializer
|
|
41
|
+
#
|
|
42
|
+
def has_many(name, options = {}, &block) # rubocop:disable Style/PredicateName
|
|
43
|
+
associate(HasManyReflection.new(name, options, block))
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# @param [Symbol] name of the association
|
|
47
|
+
# @param [Hash<Symbol => any>] options for the reflection
|
|
48
|
+
# @return [void]
|
|
49
|
+
#
|
|
50
|
+
# @example
|
|
51
|
+
# belongs_to :author, serializer: AuthorSerializer
|
|
52
|
+
#
|
|
53
|
+
def belongs_to(name, options = {}, &block)
|
|
54
|
+
associate(BelongsToReflection.new(name, options, block))
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# @param [Symbol] name of the association
|
|
58
|
+
# @param [Hash<Symbol => any>] options for the reflection
|
|
59
|
+
# @return [void]
|
|
60
|
+
#
|
|
61
|
+
# @example
|
|
62
|
+
# has_one :author, serializer: AuthorSerializer
|
|
63
|
+
#
|
|
64
|
+
def has_one(name, options = {}, &block) # rubocop:disable Style/PredicateName
|
|
65
|
+
associate(HasOneReflection.new(name, options, block))
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
# Add reflection and define {name} accessor.
|
|
71
|
+
# @param [ActiveModel::Serializer::Reflection] reflection
|
|
72
|
+
# @return [void]
|
|
73
|
+
#
|
|
74
|
+
# @api private
|
|
75
|
+
#
|
|
76
|
+
def associate(reflection)
|
|
77
|
+
key = reflection.options[:key] || reflection.name
|
|
78
|
+
self._reflections[key] = reflection
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# @param [JSONAPI::IncludeDirective] include_directive (defaults to the
|
|
83
|
+
# +default_include_directive+ config value when not provided)
|
|
84
|
+
# @return [Enumerator<Association>]
|
|
85
|
+
#
|
|
86
|
+
def associations(include_directive = ActiveModelSerializers.default_include_directive, include_slice = nil)
|
|
87
|
+
include_slice ||= include_directive
|
|
88
|
+
return unless object
|
|
89
|
+
|
|
90
|
+
Enumerator.new do |y|
|
|
91
|
+
self.class._reflections.values.each do |reflection|
|
|
92
|
+
next if reflection.excluded?(self)
|
|
93
|
+
key = reflection.options.fetch(:key, reflection.name)
|
|
94
|
+
next unless include_directive.key?(key)
|
|
95
|
+
|
|
96
|
+
y.yield reflection.build_association(self, instance_options, include_slice)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
module ActiveModel
|
|
2
|
+
class Serializer
|
|
3
|
+
module Attributes
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
|
|
6
|
+
included do
|
|
7
|
+
with_options instance_writer: false, instance_reader: false do |serializer|
|
|
8
|
+
serializer.class_attribute :_attributes_data # @api private
|
|
9
|
+
self._attributes_data ||= {}
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
extend ActiveSupport::Autoload
|
|
13
|
+
autoload :Attribute
|
|
14
|
+
|
|
15
|
+
# Return the +attributes+ of +object+ as presented
|
|
16
|
+
# by the serializer.
|
|
17
|
+
def attributes(requested_attrs = nil, reload = false)
|
|
18
|
+
@attributes = nil if reload
|
|
19
|
+
@attributes ||= self.class._attributes_data.each_with_object({}) do |(key, attr), hash|
|
|
20
|
+
next if attr.excluded?(self)
|
|
21
|
+
next unless requested_attrs.nil? || requested_attrs.include?(key)
|
|
22
|
+
hash[key] = attr.value(self)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
module ClassMethods
|
|
28
|
+
def inherited(base)
|
|
29
|
+
super
|
|
30
|
+
base._attributes_data = _attributes_data.dup
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# @example
|
|
34
|
+
# class AdminAuthorSerializer < ActiveModel::Serializer
|
|
35
|
+
# attributes :id, :name, :recent_edits
|
|
36
|
+
def attributes(*attrs)
|
|
37
|
+
attrs = attrs.first if attrs.first.class == Array
|
|
38
|
+
|
|
39
|
+
attrs.each do |attr|
|
|
40
|
+
attribute(attr)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# @example
|
|
45
|
+
# class AdminAuthorSerializer < ActiveModel::Serializer
|
|
46
|
+
# attributes :id, :recent_edits
|
|
47
|
+
# attribute :name, key: :title
|
|
48
|
+
#
|
|
49
|
+
# attribute :full_name do
|
|
50
|
+
# "#{object.first_name} #{object.last_name}"
|
|
51
|
+
# end
|
|
52
|
+
#
|
|
53
|
+
# def recent_edits
|
|
54
|
+
# object.edits.last(5)
|
|
55
|
+
# end
|
|
56
|
+
def attribute(attr, options = {}, &block)
|
|
57
|
+
key = options.fetch(:key, attr)
|
|
58
|
+
_attributes_data[key] = Attribute.new(attr, options, block)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# @api private
|
|
62
|
+
# keys of attributes
|
|
63
|
+
# @see Serializer::attribute
|
|
64
|
+
def _attributes
|
|
65
|
+
_attributes_data.keys
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# @api private
|
|
69
|
+
# maps attribute value to explicit key name
|
|
70
|
+
# @see Serializer::attribute
|
|
71
|
+
# @see FragmentCache#fragment_serializer
|
|
72
|
+
def _attributes_keys
|
|
73
|
+
_attributes_data
|
|
74
|
+
.each_with_object({}) do |(key, attr), hash|
|
|
75
|
+
next if key == attr.name
|
|
76
|
+
hash[attr.name] = { key: key }
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|