active_model_serializers 0.10.3 → 0.10.12
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/CHANGELOG.md +154 -2
- data/README.md +153 -15
- data/lib/action_controller/serialization.rb +11 -1
- data/lib/active_model/serializable_resource.rb +2 -0
- data/lib/active_model/serializer.rb +275 -81
- data/lib/active_model/serializer/adapter.rb +2 -0
- data/lib/active_model/serializer/adapter/attributes.rb +2 -0
- data/lib/active_model/serializer/adapter/base.rb +2 -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/array_serializer.rb +2 -0
- data/lib/active_model/serializer/association.rb +53 -14
- data/lib/active_model/serializer/attribute.rb +2 -0
- data/lib/active_model/serializer/belongs_to_reflection.rb +7 -1
- data/lib/active_model/serializer/collection_serializer.rb +8 -5
- data/lib/active_model/serializer/concerns/caching.rb +36 -23
- data/lib/active_model/serializer/error_serializer.rb +2 -0
- data/lib/active_model/serializer/errors_serializer.rb +2 -0
- data/lib/active_model/serializer/field.rb +2 -0
- data/lib/active_model/serializer/fieldset.rb +3 -1
- data/lib/active_model/serializer/has_many_reflection.rb +6 -1
- data/lib/active_model/serializer/has_one_reflection.rb +3 -1
- 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 +2 -0
- data/lib/active_model/serializer/null.rb +2 -0
- data/lib/active_model/serializer/reflection.rb +122 -73
- data/lib/active_model/serializer/version.rb +3 -1
- data/lib/active_model_serializers.rb +29 -11
- data/lib/active_model_serializers/adapter.rb +3 -1
- data/lib/active_model_serializers/adapter/attributes.rb +23 -0
- data/lib/active_model_serializers/adapter/base.rb +4 -2
- data/lib/active_model_serializers/adapter/json.rb +2 -0
- data/lib/active_model_serializers/adapter/json_api.rb +44 -26
- 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 +2 -0
- data/lib/active_model_serializers/adapter/json_api/meta.rb +2 -0
- data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +42 -21
- data/lib/active_model_serializers/adapter/json_api/relationship.rb +52 -9
- data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +35 -18
- data/lib/active_model_serializers/adapter/null.rb +2 -0
- data/lib/active_model_serializers/callbacks.rb +2 -0
- data/lib/active_model_serializers/deprecate.rb +2 -0
- data/lib/active_model_serializers/deserialization.rb +2 -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 +2 -0
- data/lib/active_model_serializers/model.rb +111 -30
- data/lib/active_model_serializers/model/caching.rb +25 -0
- data/lib/active_model_serializers/railtie.rb +4 -0
- data/lib/active_model_serializers/register_jsonapi_renderer.rb +2 -0
- data/lib/active_model_serializers/serializable_resource.rb +4 -2
- data/lib/active_model_serializers/serialization_context.rb +2 -0
- data/lib/active_model_serializers/test.rb +2 -0
- data/lib/active_model_serializers/test/schema.rb +4 -2
- data/lib/active_model_serializers/test/serializer.rb +2 -0
- data/lib/generators/rails/resource_override.rb +3 -1
- data/lib/generators/rails/serializer_generator.rb +2 -0
- data/lib/grape/active_model_serializers.rb +2 -0
- data/lib/grape/formatters/active_model_serializers.rb +2 -0
- data/lib/grape/helpers/active_model_serializers.rb +2 -0
- data/lib/tasks/rubocop.rake +55 -0
- metadata +74 -291
- data/.github/ISSUE_TEMPLATE.md +0 -29
- data/.github/PULL_REQUEST_TEMPLATE.md +0 -15
- data/.gitignore +0 -35
- data/.rubocop.yml +0 -102
- data/.simplecov +0 -110
- data/.travis.yml +0 -51
- data/CODE_OF_CONDUCT.md +0 -74
- data/CONTRIBUTING.md +0 -105
- data/Gemfile +0 -56
- data/Rakefile +0 -103
- data/active_model_serializers.gemspec +0 -62
- data/appveyor.yml +0 -24
- data/bin/bench +0 -171
- data/bin/bench_regression +0 -316
- data/bin/serve_benchmark +0 -39
- data/docs/ARCHITECTURE.md +0 -125
- data/docs/README.md +0 -42
- data/docs/STYLE.md +0 -58
- data/docs/general/adapters.md +0 -247
- data/docs/general/caching.md +0 -58
- data/docs/general/configuration_options.md +0 -169
- data/docs/general/deserialization.md +0 -100
- data/docs/general/fields.md +0 -31
- data/docs/general/getting_started.md +0 -133
- data/docs/general/instrumentation.md +0 -40
- data/docs/general/key_transforms.md +0 -40
- data/docs/general/logging.md +0 -14
- data/docs/general/rendering.md +0 -294
- data/docs/general/serializers.md +0 -461
- data/docs/how-open-source-maintained.jpg +0 -0
- data/docs/howto/add_pagination_links.md +0 -138
- data/docs/howto/add_relationship_links.md +0 -137
- data/docs/howto/add_root_key.md +0 -55
- data/docs/howto/grape_integration.md +0 -42
- data/docs/howto/outside_controller_use.md +0 -65
- data/docs/howto/passing_arbitrary_options.md +0 -27
- data/docs/howto/serialize_poro.md +0 -32
- data/docs/howto/test.md +0 -154
- data/docs/howto/upgrade_from_0_8_to_0_10.md +0 -265
- data/docs/integrations/ember-and-json-api.md +0 -144
- data/docs/integrations/grape.md +0 -19
- data/docs/jsonapi/errors.md +0 -56
- data/docs/jsonapi/schema.md +0 -151
- data/docs/jsonapi/schema/schema.json +0 -366
- data/docs/rfcs/0000-namespace.md +0 -106
- data/docs/rfcs/template.md +0 -15
- data/lib/active_model/serializer/collection_reflection.rb +0 -7
- data/lib/active_model/serializer/concerns/associations.rb +0 -102
- data/lib/active_model/serializer/concerns/attributes.rb +0 -82
- data/lib/active_model/serializer/concerns/configuration.rb +0 -59
- data/lib/active_model/serializer/concerns/links.rb +0 -35
- data/lib/active_model/serializer/concerns/meta.rb +0 -29
- data/lib/active_model/serializer/concerns/type.rb +0 -25
- data/lib/active_model/serializer/singular_reflection.rb +0 -7
- data/lib/active_model_serializers/key_transform.rb +0 -74
- data/test/action_controller/adapter_selector_test.rb +0 -53
- data/test/action_controller/explicit_serializer_test.rb +0 -135
- data/test/action_controller/json/include_test.rb +0 -246
- data/test/action_controller/json_api/deserialization_test.rb +0 -112
- data/test/action_controller/json_api/errors_test.rb +0 -40
- data/test/action_controller/json_api/fields_test.rb +0 -57
- data/test/action_controller/json_api/linked_test.rb +0 -202
- data/test/action_controller/json_api/pagination_test.rb +0 -116
- data/test/action_controller/json_api/transform_test.rb +0 -181
- data/test/action_controller/lookup_proc_test.rb +0 -49
- data/test/action_controller/namespace_lookup_test.rb +0 -226
- data/test/action_controller/serialization_scope_name_test.rb +0 -229
- data/test/action_controller/serialization_test.rb +0 -472
- data/test/active_model_serializers/adapter_for_test.rb +0 -208
- data/test/active_model_serializers/json_pointer_test.rb +0 -22
- data/test/active_model_serializers/key_transform_test.rb +0 -297
- data/test/active_model_serializers/logging_test.rb +0 -77
- data/test/active_model_serializers/model_test.rb +0 -22
- data/test/active_model_serializers/railtie_test_isolated.rb +0 -63
- data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +0 -143
- data/test/active_model_serializers/serialization_context_test_isolated.rb +0 -71
- data/test/active_model_serializers/test/schema_test.rb +0 -130
- data/test/active_model_serializers/test/serializer_test.rb +0 -62
- data/test/active_record_test.rb +0 -9
- data/test/adapter/attributes_test.rb +0 -43
- data/test/adapter/deprecation_test.rb +0 -100
- data/test/adapter/json/belongs_to_test.rb +0 -45
- data/test/adapter/json/collection_test.rb +0 -104
- data/test/adapter/json/has_many_test.rb +0 -45
- data/test/adapter/json/transform_test.rb +0 -93
- data/test/adapter/json_api/belongs_to_test.rb +0 -155
- data/test/adapter/json_api/collection_test.rb +0 -96
- data/test/adapter/json_api/errors_test.rb +0 -76
- data/test/adapter/json_api/fields_test.rb +0 -88
- data/test/adapter/json_api/has_many_embed_ids_test.rb +0 -43
- data/test/adapter/json_api/has_many_explicit_serializer_test.rb +0 -96
- data/test/adapter/json_api/has_many_test.rb +0 -165
- data/test/adapter/json_api/has_one_test.rb +0 -80
- data/test/adapter/json_api/include_data_if_sideloaded_test.rb +0 -166
- data/test/adapter/json_api/json_api_test.rb +0 -33
- data/test/adapter/json_api/linked_test.rb +0 -413
- data/test/adapter/json_api/links_test.rb +0 -95
- data/test/adapter/json_api/pagination_links_test.rb +0 -193
- data/test/adapter/json_api/parse_test.rb +0 -137
- data/test/adapter/json_api/relationship_test.rb +0 -397
- data/test/adapter/json_api/resource_identifier_test.rb +0 -110
- data/test/adapter/json_api/resource_meta_test.rb +0 -100
- data/test/adapter/json_api/toplevel_jsonapi_test.rb +0 -82
- data/test/adapter/json_api/transform_test.rb +0 -504
- data/test/adapter/json_api/type_test.rb +0 -61
- data/test/adapter/json_test.rb +0 -46
- data/test/adapter/null_test.rb +0 -22
- data/test/adapter/polymorphic_test.rb +0 -171
- data/test/adapter_test.rb +0 -67
- data/test/array_serializer_test.rb +0 -22
- data/test/benchmark/app.rb +0 -65
- data/test/benchmark/benchmarking_support.rb +0 -67
- data/test/benchmark/bm_active_record.rb +0 -81
- data/test/benchmark/bm_adapter.rb +0 -38
- data/test/benchmark/bm_caching.rb +0 -119
- data/test/benchmark/bm_lookup_chain.rb +0 -83
- data/test/benchmark/bm_transform.rb +0 -45
- data/test/benchmark/config.ru +0 -3
- data/test/benchmark/controllers.rb +0 -83
- data/test/benchmark/fixtures.rb +0 -219
- data/test/cache_test.rb +0 -579
- data/test/collection_serializer_test.rb +0 -110
- data/test/fixtures/active_record.rb +0 -78
- data/test/fixtures/poro.rb +0 -286
- data/test/generators/scaffold_controller_generator_test.rb +0 -24
- data/test/generators/serializer_generator_test.rb +0 -74
- data/test/grape_test.rb +0 -178
- data/test/lint_test.rb +0 -49
- data/test/logger_test.rb +0 -20
- data/test/poro_test.rb +0 -9
- data/test/serializable_resource_test.rb +0 -79
- data/test/serializers/association_macros_test.rb +0 -37
- data/test/serializers/associations_test.rb +0 -370
- data/test/serializers/attribute_test.rb +0 -151
- data/test/serializers/attributes_test.rb +0 -52
- data/test/serializers/caching_configuration_test_isolated.rb +0 -170
- data/test/serializers/configuration_test.rb +0 -32
- data/test/serializers/fieldset_test.rb +0 -14
- data/test/serializers/meta_test.rb +0 -202
- data/test/serializers/options_test.rb +0 -21
- data/test/serializers/read_attribute_for_serialization_test.rb +0 -79
- data/test/serializers/root_test.rb +0 -21
- data/test/serializers/serialization_test.rb +0 -55
- data/test/serializers/serializer_for_test.rb +0 -136
- data/test/serializers/serializer_for_with_namespace_test.rb +0 -87
- data/test/support/custom_schemas/active_model_serializers/test/schema_test/my/index.json +0 -6
- data/test/support/isolated_unit.rb +0 -82
- data/test/support/rails5_shims.rb +0 -53
- data/test/support/rails_app.rb +0 -36
- data/test/support/schemas/active_model_serializers/test/schema_test/my/index.json +0 -6
- data/test/support/schemas/active_model_serializers/test/schema_test/my/show.json +0 -6
- data/test/support/schemas/custom/show.json +0 -7
- data/test/support/schemas/hyper_schema.json +0 -93
- data/test/support/schemas/render_using_json_api.json +0 -43
- data/test/support/schemas/simple_json_pointers.json +0 -10
- data/test/support/serialization_testing.rb +0 -71
- data/test/test_helper.rb +0 -58
|
@@ -1,34 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'active_model/serializer/lazy_association'
|
|
4
|
+
|
|
1
5
|
module ActiveModel
|
|
2
6
|
class Serializer
|
|
3
7
|
# This class holds all information about serializer's association.
|
|
4
8
|
#
|
|
5
|
-
# @
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
# @api private
|
|
10
|
+
Association = Struct.new(:reflection, :association_options) do
|
|
11
|
+
attr_reader :lazy_association
|
|
12
|
+
delegate :object, :include_data?, :virtual_value, :collection?, to: :lazy_association
|
|
13
|
+
|
|
14
|
+
def initialize(*)
|
|
15
|
+
super
|
|
16
|
+
@lazy_association = LazyAssociation.new(reflection, association_options)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# @return [Symbol]
|
|
20
|
+
delegate :name, to: :reflection
|
|
21
|
+
|
|
13
22
|
# @return [Symbol]
|
|
14
23
|
def key
|
|
15
|
-
|
|
24
|
+
reflection_options.fetch(:key, name)
|
|
16
25
|
end
|
|
17
26
|
|
|
18
|
-
# @return [
|
|
19
|
-
def
|
|
20
|
-
|
|
27
|
+
# @return [True,False]
|
|
28
|
+
def key?
|
|
29
|
+
reflection_options.key?(:key)
|
|
21
30
|
end
|
|
22
31
|
|
|
23
32
|
# @return [Hash]
|
|
24
33
|
def links
|
|
25
|
-
|
|
34
|
+
reflection_options.fetch(:links) || {}
|
|
26
35
|
end
|
|
27
36
|
|
|
28
37
|
# @return [Hash, nil]
|
|
38
|
+
# This gets mutated, so cannot use the cached reflection_options
|
|
29
39
|
def meta
|
|
30
|
-
options[:meta]
|
|
40
|
+
reflection.options[:meta]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def belongs_to?
|
|
44
|
+
reflection.foreign_key_on == :self
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def polymorphic?
|
|
48
|
+
true == reflection_options[:polymorphic]
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# @api private
|
|
52
|
+
def serializable_hash(adapter_options, adapter_instance)
|
|
53
|
+
association_serializer = lazy_association.serializer
|
|
54
|
+
return virtual_value if virtual_value
|
|
55
|
+
association_object = association_serializer && association_serializer.object
|
|
56
|
+
return unless association_object
|
|
57
|
+
|
|
58
|
+
serialization = association_serializer.serializable_hash(adapter_options, {}, adapter_instance)
|
|
59
|
+
|
|
60
|
+
if polymorphic? && serialization
|
|
61
|
+
polymorphic_type = association_object.class.name.underscore
|
|
62
|
+
serialization = { type: polymorphic_type, polymorphic_type.to_sym => serialization }
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
serialization
|
|
31
66
|
end
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
delegate :reflection_options, to: :lazy_association
|
|
32
71
|
end
|
|
33
72
|
end
|
|
34
73
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveModel
|
|
2
4
|
class Serializer
|
|
3
5
|
class CollectionSerializer
|
|
@@ -19,11 +21,10 @@ module ActiveModel
|
|
|
19
21
|
|
|
20
22
|
# @api private
|
|
21
23
|
def serializable_hash(adapter_options, options, adapter_instance)
|
|
22
|
-
include_directive
|
|
23
|
-
|
|
24
|
-
adapter_opts = adapter_options.merge(include_directive: include_directive)
|
|
24
|
+
options[:include_directive] ||= ActiveModel::Serializer.include_directive_from_options(adapter_options)
|
|
25
|
+
options[:cached_attributes] ||= ActiveModel::Serializer.cache_read_multi(self, adapter_instance, options[:include_directive])
|
|
25
26
|
serializers.map do |serializer|
|
|
26
|
-
serializer.serializable_hash(
|
|
27
|
+
serializer.serializable_hash(adapter_options, options, adapter_instance)
|
|
27
28
|
end
|
|
28
29
|
end
|
|
29
30
|
|
|
@@ -46,7 +47,9 @@ module ActiveModel
|
|
|
46
47
|
# 3. get from collection name, if a named collection
|
|
47
48
|
key ||= object.respond_to?(:name) ? object.name && object.name.underscore : nil
|
|
48
49
|
# 4. key may be nil for empty collection and no serializer option
|
|
49
|
-
key
|
|
50
|
+
key &&= key.pluralize
|
|
51
|
+
# 5. fail if the key cannot be determined
|
|
52
|
+
key || fail(ArgumentError, 'Cannot infer root key from collection type. Please specify the root or each_serializer option, or render a JSON String')
|
|
50
53
|
end
|
|
51
54
|
# rubocop:enable Metrics/CyclomaticComplexity
|
|
52
55
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveModel
|
|
2
4
|
class Serializer
|
|
3
5
|
UndefinedCacheKey = Class.new(StandardError)
|
|
@@ -40,9 +42,9 @@ module ActiveModel
|
|
|
40
42
|
|
|
41
43
|
module ClassMethods
|
|
42
44
|
def inherited(base)
|
|
43
|
-
super
|
|
44
45
|
caller_line = caller[1]
|
|
45
46
|
base._cache_digest_file_path = caller_line
|
|
47
|
+
super
|
|
46
48
|
end
|
|
47
49
|
|
|
48
50
|
def _cache_digest
|
|
@@ -54,7 +56,8 @@ module ActiveModel
|
|
|
54
56
|
def digest_caller_file(caller_line)
|
|
55
57
|
serializer_file_path = caller_line[CALLER_FILE]
|
|
56
58
|
serializer_file_contents = IO.read(serializer_file_path)
|
|
57
|
-
Digest::MD5
|
|
59
|
+
algorithm = ActiveModelSerializers.config.use_sha1_digests ? Digest::SHA1 : Digest::MD5
|
|
60
|
+
algorithm.hexdigest(serializer_file_contents)
|
|
58
61
|
rescue TypeError, Errno::ENOENT
|
|
59
62
|
warn <<-EOF.strip_heredoc
|
|
60
63
|
Cannot digest non-existent file: '#{caller_line}'.
|
|
@@ -68,6 +71,18 @@ module ActiveModel
|
|
|
68
71
|
_cache_options && _cache_options[:skip_digest]
|
|
69
72
|
end
|
|
70
73
|
|
|
74
|
+
# @api private
|
|
75
|
+
# maps attribute value to explicit key name
|
|
76
|
+
# @see Serializer::attribute
|
|
77
|
+
# @see Serializer::fragmented_attributes
|
|
78
|
+
def _attributes_keys
|
|
79
|
+
_attributes_data
|
|
80
|
+
.each_with_object({}) do |(key, attr), hash|
|
|
81
|
+
next if key == attr.name
|
|
82
|
+
hash[attr.name] = { key: key }
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
71
86
|
def fragmented_attributes
|
|
72
87
|
cached = _cache_only ? _cache_only : _attributes - _cache_except
|
|
73
88
|
cached = cached.map! { |field| _attributes_keys.fetch(field, field) }
|
|
@@ -158,6 +173,7 @@ module ActiveModel
|
|
|
158
173
|
|
|
159
174
|
# Read cache from cache_store
|
|
160
175
|
# @return [Hash]
|
|
176
|
+
# Used in CollectionSerializer to set :cached_attributes
|
|
161
177
|
def cache_read_multi(collection_serializer, adapter_instance, include_directive)
|
|
162
178
|
return {} if ActiveModelSerializers.config.cache_store.blank?
|
|
163
179
|
|
|
@@ -180,12 +196,14 @@ module ActiveModel
|
|
|
180
196
|
cache_keys << object_cache_key(serializer, adapter_instance)
|
|
181
197
|
|
|
182
198
|
serializer.associations(include_directive).each do |association|
|
|
183
|
-
|
|
184
|
-
|
|
199
|
+
# TODO(BF): Process relationship without evaluating lazy_association
|
|
200
|
+
association_serializer = association.lazy_association.serializer
|
|
201
|
+
if association_serializer.respond_to?(:each)
|
|
202
|
+
association_serializer.each do |sub_serializer|
|
|
185
203
|
cache_keys << object_cache_key(sub_serializer, adapter_instance)
|
|
186
204
|
end
|
|
187
205
|
else
|
|
188
|
-
cache_keys << object_cache_key(
|
|
206
|
+
cache_keys << object_cache_key(association_serializer, adapter_instance)
|
|
189
207
|
end
|
|
190
208
|
end
|
|
191
209
|
end
|
|
@@ -203,23 +221,18 @@ module ActiveModel
|
|
|
203
221
|
|
|
204
222
|
### INSTANCE METHODS
|
|
205
223
|
def fetch_attributes(fields, cached_attributes, adapter_instance)
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
attributes(fields, true)
|
|
211
|
-
end
|
|
224
|
+
key = cache_key(adapter_instance)
|
|
225
|
+
cached_attributes.fetch(key) do
|
|
226
|
+
fetch(adapter_instance, serializer_class._cache_options, key) do
|
|
227
|
+
attributes(fields, true)
|
|
212
228
|
end
|
|
213
|
-
elsif serializer_class.fragment_cache_enabled?
|
|
214
|
-
fetch_attributes_fragment(adapter_instance, cached_attributes)
|
|
215
|
-
else
|
|
216
|
-
attributes(fields, true)
|
|
217
229
|
end
|
|
218
230
|
end
|
|
219
231
|
|
|
220
|
-
def fetch(adapter_instance, cache_options = serializer_class._cache_options)
|
|
232
|
+
def fetch(adapter_instance, cache_options = serializer_class._cache_options, key = nil)
|
|
221
233
|
if serializer_class.cache_store
|
|
222
|
-
|
|
234
|
+
key ||= cache_key(adapter_instance)
|
|
235
|
+
serializer_class.cache_store.fetch(key, cache_options) do
|
|
223
236
|
yield
|
|
224
237
|
end
|
|
225
238
|
else
|
|
@@ -230,7 +243,6 @@ module ActiveModel
|
|
|
230
243
|
# 1. Determine cached fields from serializer class options
|
|
231
244
|
# 2. Get non_cached_fields and fetch cache_fields
|
|
232
245
|
# 3. Merge the two hashes using adapter_instance#fragment_cache
|
|
233
|
-
# rubocop:disable Metrics/AbcSize
|
|
234
246
|
def fetch_attributes_fragment(adapter_instance, cached_attributes = {})
|
|
235
247
|
serializer_class._cache_options ||= {}
|
|
236
248
|
serializer_class._cache_options[:key] = serializer_class._cache_key if serializer_class._cache_key
|
|
@@ -239,22 +251,21 @@ module ActiveModel
|
|
|
239
251
|
non_cached_fields = fields[:non_cached].dup
|
|
240
252
|
non_cached_hash = attributes(non_cached_fields, true)
|
|
241
253
|
include_directive = JSONAPI::IncludeDirective.new(non_cached_fields - non_cached_hash.keys)
|
|
242
|
-
non_cached_hash.merge!
|
|
254
|
+
non_cached_hash.merge! associations_hash({}, { include_directive: include_directive }, adapter_instance)
|
|
243
255
|
|
|
244
256
|
cached_fields = fields[:cached].dup
|
|
245
257
|
key = cache_key(adapter_instance)
|
|
246
258
|
cached_hash =
|
|
247
259
|
cached_attributes.fetch(key) do
|
|
248
|
-
|
|
260
|
+
fetch(adapter_instance, serializer_class._cache_options, key) do
|
|
249
261
|
hash = attributes(cached_fields, true)
|
|
250
262
|
include_directive = JSONAPI::IncludeDirective.new(cached_fields - hash.keys)
|
|
251
|
-
hash.merge!
|
|
263
|
+
hash.merge! associations_hash({}, { include_directive: include_directive }, adapter_instance)
|
|
252
264
|
end
|
|
253
265
|
end
|
|
254
266
|
# Merge both results
|
|
255
267
|
adapter_instance.fragment_cache(cached_hash, non_cached_hash)
|
|
256
268
|
end
|
|
257
|
-
# rubocop:enable Metrics/AbcSize
|
|
258
269
|
|
|
259
270
|
def cache_key(adapter_instance)
|
|
260
271
|
return @cache_key if defined?(@cache_key)
|
|
@@ -273,7 +284,9 @@ module ActiveModel
|
|
|
273
284
|
# Use object's cache_key if available, else derive a key from the object
|
|
274
285
|
# Pass the `key` option to the `cache` declaration or override this method to customize the cache key
|
|
275
286
|
def object_cache_key
|
|
276
|
-
if object.respond_to?(:
|
|
287
|
+
if object.respond_to?(:cache_key_with_version)
|
|
288
|
+
object.cache_key_with_version
|
|
289
|
+
elsif object.respond_to?(:cache_key)
|
|
277
290
|
object.cache_key
|
|
278
291
|
elsif (serializer_cache_key = (serializer_class._cache_key || serializer_class._cache_options[:key]))
|
|
279
292
|
object_time_safe = object.updated_at
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveModel
|
|
2
4
|
class Serializer
|
|
3
5
|
class Fieldset
|
|
@@ -10,7 +12,7 @@ module ActiveModel
|
|
|
10
12
|
end
|
|
11
13
|
|
|
12
14
|
def fields_for(type)
|
|
13
|
-
fields[type.singularize.to_sym] || fields[type.pluralize.to_sym]
|
|
15
|
+
fields[type.to_s.singularize.to_sym] || fields[type.to_s.pluralize.to_sym]
|
|
14
16
|
end
|
|
15
17
|
|
|
16
18
|
protected
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveModel
|
|
4
|
+
class Serializer
|
|
5
|
+
# @api private
|
|
6
|
+
LazyAssociation = Struct.new(:reflection, :association_options) do
|
|
7
|
+
REFLECTION_OPTIONS = %i(key links polymorphic meta serializer virtual_value namespace).freeze
|
|
8
|
+
|
|
9
|
+
delegate :collection?, to: :reflection
|
|
10
|
+
|
|
11
|
+
def reflection_options
|
|
12
|
+
@reflection_options ||= reflection.options.select { |k, _| REFLECTION_OPTIONS.include?(k) }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def object
|
|
16
|
+
return @object if defined?(@object)
|
|
17
|
+
@object = reflection.value(
|
|
18
|
+
association_options.fetch(:parent_serializer),
|
|
19
|
+
association_options.fetch(:include_slice)
|
|
20
|
+
)
|
|
21
|
+
end
|
|
22
|
+
alias_method :eval_reflection_block, :object
|
|
23
|
+
|
|
24
|
+
def include_data?
|
|
25
|
+
eval_reflection_block if reflection.block
|
|
26
|
+
reflection.include_data?(
|
|
27
|
+
association_options.fetch(:include_slice)
|
|
28
|
+
)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# @return [ActiveModel::Serializer, nil]
|
|
32
|
+
def serializer
|
|
33
|
+
return @serializer if defined?(@serializer)
|
|
34
|
+
if serializer_class
|
|
35
|
+
serialize_object!(object)
|
|
36
|
+
elsif !object.nil? && !object.instance_of?(Object)
|
|
37
|
+
cached_result[:virtual_value] = object
|
|
38
|
+
end
|
|
39
|
+
@serializer = cached_result[:serializer]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def virtual_value
|
|
43
|
+
cached_result[:virtual_value] || reflection_options[:virtual_value]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def serializer_class
|
|
47
|
+
return @serializer_class if defined?(@serializer_class)
|
|
48
|
+
serializer_for_options = { namespace: namespace }
|
|
49
|
+
serializer_for_options[:serializer] = reflection_options[:serializer] if reflection_options.key?(:serializer)
|
|
50
|
+
@serializer_class = association_options.fetch(:parent_serializer).class.serializer_for(object, serializer_for_options)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def cached_result
|
|
56
|
+
@cached_result ||= {}
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def serialize_object!(object)
|
|
60
|
+
if collection?
|
|
61
|
+
if (serializer = instantiate_collection_serializer(object)).nil?
|
|
62
|
+
# BUG: per #2027, JSON API resource relationships are only id and type, and hence either
|
|
63
|
+
# *require* a serializer or we need to be a little clever about figuring out the id/type.
|
|
64
|
+
# In either case, returning the raw virtual value will almost always be incorrect.
|
|
65
|
+
#
|
|
66
|
+
# Should be reflection_options[:virtual_value] or adapter needs to figure out what to do
|
|
67
|
+
# with an object that is non-nil and has no defined serializer.
|
|
68
|
+
cached_result[:virtual_value] = object.try(:as_json) || object
|
|
69
|
+
else
|
|
70
|
+
cached_result[:serializer] = serializer
|
|
71
|
+
end
|
|
72
|
+
else
|
|
73
|
+
cached_result[:serializer] = instantiate_serializer(object)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def instantiate_serializer(object)
|
|
78
|
+
serializer_options = association_options.fetch(:parent_serializer_options).except(:serializer)
|
|
79
|
+
serializer_options[:serializer_context_class] = association_options.fetch(:parent_serializer).class
|
|
80
|
+
serializer = reflection_options.fetch(:serializer, nil)
|
|
81
|
+
serializer_options[:serializer] = serializer if serializer
|
|
82
|
+
serializer_options[:namespace] = reflection_options[:namespace] if reflection_options[:namespace]
|
|
83
|
+
serializer_class.new(object, serializer_options)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def instantiate_collection_serializer(object)
|
|
87
|
+
serializer = catch(:no_serializer) do
|
|
88
|
+
instantiate_serializer(object)
|
|
89
|
+
end
|
|
90
|
+
serializer
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def namespace
|
|
94
|
+
reflection_options[:namespace] ||
|
|
95
|
+
association_options.fetch(:parent_serializer_options)[:namespace]
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|