mirror of
https://github.com/ditkrg/active_model_serializers.git
synced 2026-01-23 06:16:50 +00:00
Move adapter cache properties to class level (where they belong).
This commit is contained in:
parent
516e7da8ff
commit
913f396bb1
@ -109,6 +109,10 @@ module ActiveModel
|
||||
end
|
||||
end
|
||||
|
||||
def self.serialization_adapter_instance
|
||||
@serialization_adapter_instance ||= ActiveModelSerializers::Adapter::Attributes
|
||||
end
|
||||
|
||||
attr_accessor :object, :root, :scope
|
||||
|
||||
# `scope_name` is set as :current_user by default in the controller.
|
||||
@ -163,8 +167,7 @@ module ActiveModel
|
||||
def serializable_hash(adapter_opts = nil)
|
||||
adapter_opts ||= {}
|
||||
adapter_opts = { include: '*' }.merge!(adapter_opts)
|
||||
adapter_instance = ActiveModelSerializers::Adapter::Attributes.new(self, adapter_opts)
|
||||
serialize(adapter_opts, {}, adapter_instance)
|
||||
serialize(adapter_opts)
|
||||
end
|
||||
alias to_hash serializable_hash
|
||||
alias to_h serializable_hash
|
||||
@ -197,7 +200,7 @@ module ActiveModel
|
||||
end
|
||||
|
||||
# @api private
|
||||
def serialize(adapter_options, options, adapter_instance)
|
||||
def serialize(adapter_options, options = {}, adapter_instance = self.class.serialization_adapter_instance)
|
||||
options[:include_directive] ||= ActiveModel::Serializer.include_directive_from_options(adapter_options)
|
||||
cached_attributes = adapter_options[:cached_attributes] ||= {}
|
||||
resource = cached_attributes(options[:fields], cached_attributes, adapter_instance)
|
||||
|
||||
@ -318,7 +318,7 @@ module ActiveModel
|
||||
|
||||
parts = []
|
||||
parts << object_cache_key
|
||||
parts << adapter_instance.cached_name
|
||||
parts << adapter_instance.cache_key
|
||||
parts << self.class._cache_digest unless self.class._skip_digest?
|
||||
@cache_key = parts.join('/')
|
||||
end
|
||||
|
||||
@ -51,6 +51,10 @@ module ActiveModelSerializers
|
||||
self
|
||||
end
|
||||
|
||||
def registered_name(adapter_class)
|
||||
ADAPTER_MAP.key adapter_class
|
||||
end
|
||||
|
||||
# @param adapter [String, Symbol, Class] name to fetch adapter by
|
||||
# @return [ActiveModelSerializers::Adapter] subclass of Adapter
|
||||
# @raise [UnknownAdapterError]
|
||||
|
||||
@ -8,6 +8,40 @@ module ActiveModelSerializers
|
||||
ActiveModelSerializers::Adapter.register(subclass)
|
||||
end
|
||||
|
||||
# Sets the default transform for the adapter.
|
||||
#
|
||||
# @return [Symbol] the default transform for the adapter
|
||||
def self.default_key_transform
|
||||
:unaltered
|
||||
end
|
||||
|
||||
# Determines the transform to use in order of precedence:
|
||||
# adapter option, global config, adapter default.
|
||||
#
|
||||
# @param options [Object]
|
||||
# @return [Symbol] the transform to use
|
||||
def self.transform(options)
|
||||
return options[:key_transform] if options && options[:key_transform]
|
||||
ActiveModelSerializers.config.key_transform || default_key_transform
|
||||
end
|
||||
|
||||
# Transforms the casing of the supplied value.
|
||||
#
|
||||
# @param value [Object] the value to be transformed
|
||||
# @param options [Object] serializable resource options
|
||||
# @return [Symbol] the default transform for the adapter
|
||||
def self.transform_key_casing!(value, options)
|
||||
KeyTransform.send(transform(options), value)
|
||||
end
|
||||
|
||||
def self.cache_key
|
||||
@cache_key ||= ActiveModelSerializers::Adapter.registered_name(self)
|
||||
end
|
||||
|
||||
def self.fragment_cache(cached_hash, non_cached_hash)
|
||||
non_cached_hash.merge cached_hash
|
||||
end
|
||||
|
||||
attr_reader :serializer, :instance_options
|
||||
|
||||
def initialize(serializer, options = {})
|
||||
@ -15,10 +49,6 @@ module ActiveModelSerializers
|
||||
@instance_options = options
|
||||
end
|
||||
|
||||
def cached_name
|
||||
@cached_name ||= self.class.name.demodulize.underscore
|
||||
end
|
||||
|
||||
# Subclasses that implement this method must first call
|
||||
# options = serialization_options(options)
|
||||
def serializable_hash(_options = nil)
|
||||
@ -29,8 +59,12 @@ module ActiveModelSerializers
|
||||
serializable_hash(options)
|
||||
end
|
||||
|
||||
def cache_key
|
||||
self.class.cache_key
|
||||
end
|
||||
|
||||
def fragment_cache(cached_hash, non_cached_hash)
|
||||
non_cached_hash.merge cached_hash
|
||||
self.class.fragment_cache(cached_hash, non_cached_hash)
|
||||
end
|
||||
|
||||
private
|
||||
@ -44,34 +78,6 @@ module ActiveModelSerializers
|
||||
def root
|
||||
serializer.json_key.to_sym if serializer.json_key
|
||||
end
|
||||
|
||||
class << self
|
||||
# Sets the default transform for the adapter.
|
||||
#
|
||||
# @return [Symbol] the default transform for the adapter
|
||||
def default_key_transform
|
||||
:unaltered
|
||||
end
|
||||
|
||||
# Determines the transform to use in order of precedence:
|
||||
# adapter option, global config, adapter default.
|
||||
#
|
||||
# @param options [Object]
|
||||
# @return [Symbol] the transform to use
|
||||
def transform(options)
|
||||
return options[:key_transform] if options && options[:key_transform]
|
||||
ActiveModelSerializers.config.key_transform || default_key_transform
|
||||
end
|
||||
|
||||
# Transforms the casing of the supplied value.
|
||||
#
|
||||
# @param value [Object] the value to be transformed
|
||||
# @param options [Object] serializable resource options
|
||||
# @return [Symbol] the default transform for the adapter
|
||||
def transform_key_casing!(value, options)
|
||||
KeyTransform.send(transform(options), value)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -31,16 +31,27 @@ module ActiveModelSerializers
|
||||
autoload :Error
|
||||
autoload :Deserialization
|
||||
|
||||
def self.default_key_transform
|
||||
:dash
|
||||
end
|
||||
|
||||
def self.fragment_cache(cached_hash, non_cached_hash, root = true)
|
||||
core_cached = cached_hash.first
|
||||
core_non_cached = non_cached_hash.first
|
||||
no_root_cache = cached_hash.delete_if { |key, _value| key == core_cached[0] }
|
||||
no_root_non_cache = non_cached_hash.delete_if { |key, _value| key == core_non_cached[0] }
|
||||
cached_resource = (core_cached[1]) ? core_cached[1].deep_merge(core_non_cached[1]) : core_non_cached[1]
|
||||
hash = root ? { root => cached_resource } : cached_resource
|
||||
|
||||
hash.deep_merge no_root_non_cache.deep_merge no_root_cache
|
||||
end
|
||||
|
||||
def initialize(serializer, options = {})
|
||||
super
|
||||
@include_directive = JSONAPI::IncludeDirective.new(options[:include], allow_wildcard: true)
|
||||
@fieldset = options[:fieldset] || ActiveModel::Serializer::Fieldset.new(options.delete(:fields))
|
||||
end
|
||||
|
||||
def self.default_key_transform
|
||||
:dash
|
||||
end
|
||||
|
||||
# {http://jsonapi.org/format/#crud Requests are transactional, i.e. success or failure}
|
||||
# {http://jsonapi.org/format/#document-top-level data and errors MUST NOT coexist in the same document.}
|
||||
def serializable_hash(*)
|
||||
@ -52,6 +63,11 @@ module ActiveModelSerializers
|
||||
self.class.transform_key_casing!(document, instance_options)
|
||||
end
|
||||
|
||||
def fragment_cache(cached_hash, non_cached_hash)
|
||||
root = !instance_options.include?(:include)
|
||||
self.class.fragment_cache(cached_hash, non_cached_hash, root)
|
||||
end
|
||||
|
||||
# {http://jsonapi.org/format/#document-top-level Primary data}
|
||||
# definition:
|
||||
# ☐ toplevel_data (required)
|
||||
@ -174,18 +190,6 @@ module ActiveModelSerializers
|
||||
hash
|
||||
end
|
||||
|
||||
def fragment_cache(cached_hash, non_cached_hash)
|
||||
root = false if instance_options.include?(:include)
|
||||
core_cached = cached_hash.first
|
||||
core_non_cached = non_cached_hash.first
|
||||
no_root_cache = cached_hash.delete_if { |key, _value| key == core_cached[0] }
|
||||
no_root_non_cache = non_cached_hash.delete_if { |key, _value| key == core_non_cached[0] }
|
||||
cached_resource = (core_cached[1]) ? core_cached[1].deep_merge(core_non_cached[1]) : core_non_cached[1]
|
||||
hash = root ? { root => cached_resource } : cached_resource
|
||||
|
||||
hash.deep_merge no_root_non_cache.deep_merge no_root_cache
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
attr_reader :fieldset
|
||||
|
||||
@ -102,13 +102,13 @@ module ActiveModelSerializers
|
||||
|
||||
render_object_with_cache(uncached_author)
|
||||
key = "#{uncached_author_serializer.class._cache_key}/#{uncached_author_serializer.object.id}-#{uncached_author_serializer.object.updated_at.strftime("%Y%m%d%H%M%S%9N")}"
|
||||
key = "#{key}/#{adapter.cached_name}"
|
||||
key = "#{key}/#{adapter.cache_key}"
|
||||
assert_equal(uncached_author_serializer.attributes.to_json, cache_store.fetch(key).to_json)
|
||||
end
|
||||
|
||||
def test_default_cache_key_fallback
|
||||
render_object_with_cache(@comment)
|
||||
key = "#{@comment.cache_key}/#{adapter.cached_name}"
|
||||
key = "#{@comment.cache_key}/#{adapter.cache_key}"
|
||||
assert_equal(@comment_serializer.attributes.to_json, cache_store.fetch(key).to_json)
|
||||
end
|
||||
|
||||
@ -139,9 +139,9 @@ module ActiveModelSerializers
|
||||
Timecop.freeze(Time.current) do
|
||||
render_object_with_cache(@post)
|
||||
|
||||
key = "#{@post.cache_key}/#{adapter.cached_name}"
|
||||
key = "#{@post.cache_key}/#{adapter.cache_key}"
|
||||
assert_equal(@post_serializer.attributes, cache_store.fetch(key))
|
||||
key = "#{@comment.cache_key}/#{adapter.cached_name}"
|
||||
key = "#{@comment.cache_key}/#{adapter.cache_key}"
|
||||
assert_equal(@comment_serializer.attributes, cache_store.fetch(key))
|
||||
end
|
||||
end
|
||||
@ -152,9 +152,9 @@ module ActiveModelSerializers
|
||||
render_object_with_cache(@post)
|
||||
|
||||
# Check if it cached the objects separately
|
||||
key = "#{@post.cache_key}/#{adapter.cached_name}"
|
||||
key = "#{@post.cache_key}/#{adapter.cache_key}"
|
||||
assert_equal(@post_serializer.attributes, cache_store.fetch(key))
|
||||
key = "#{@comment.cache_key}/#{adapter.cached_name}"
|
||||
key = "#{@comment.cache_key}/#{adapter.cache_key}"
|
||||
assert_equal(@comment_serializer.attributes, cache_store.fetch(key))
|
||||
|
||||
# Simulating update on comments relationship with Post
|
||||
@ -166,9 +166,9 @@ module ActiveModelSerializers
|
||||
render_object_with_cache(@post)
|
||||
|
||||
# Check if the the new comment was cached
|
||||
key = "#{new_comment.cache_key}/#{adapter.cached_name}"
|
||||
key = "#{new_comment.cache_key}/#{adapter.cache_key}"
|
||||
assert_equal(new_comment_serializer.attributes, cache_store.fetch(key))
|
||||
key = "#{@post.cache_key}/#{adapter.cached_name}"
|
||||
key = "#{@post.cache_key}/#{adapter.cache_key}"
|
||||
assert_equal(@post_serializer.attributes, cache_store.fetch(key))
|
||||
end
|
||||
end
|
||||
@ -184,7 +184,7 @@ module ActiveModelSerializers
|
||||
hash = render_object_with_cache(@location)
|
||||
|
||||
assert_equal(hash, expected_result)
|
||||
key = "#{@location.cache_key}/#{adapter.cached_name}"
|
||||
key = "#{@location.cache_key}/#{adapter.cache_key}"
|
||||
assert_equal({ place: 'Nowhere' }, cache_store.fetch(key))
|
||||
end
|
||||
|
||||
@ -276,7 +276,7 @@ module ActiveModelSerializers
|
||||
|
||||
def test_uses_file_digest_in_cache_key
|
||||
render_object_with_cache(@blog)
|
||||
key = "#{@blog.cache_key}/#{adapter.cached_name}/#{::Model::FILE_DIGEST}"
|
||||
key = "#{@blog.cache_key}/#{adapter.cache_key}/#{::Model::FILE_DIGEST}"
|
||||
assert_equal(@blog_serializer.attributes, cache_store.fetch(key))
|
||||
end
|
||||
|
||||
@ -291,7 +291,7 @@ module ActiveModelSerializers
|
||||
actual = ActiveModel::Serializer.object_cache_keys(serializable.adapter.serializer, serializable.adapter, include_directive)
|
||||
|
||||
assert_equal 3, actual.size
|
||||
assert actual.any? { |key| key == "comment/1/#{serializable.adapter.cached_name}" }
|
||||
assert actual.any? { |key| key == "comment/1/#{serializable.adapter.cache_key}" }
|
||||
assert actual.any? { |key| key =~ %r{post/post-\d+} }
|
||||
assert actual.any? { |key| key =~ %r{author/author-\d+} }
|
||||
end
|
||||
@ -306,13 +306,13 @@ module ActiveModelSerializers
|
||||
include_directive = ActiveModelSerializers.default_include_directive
|
||||
cached_attributes = ActiveModel::Serializer.cache_read_multi(serializer, attributes, include_directive)
|
||||
|
||||
assert_equal cached_attributes["#{@comment.cache_key}/#{attributes.cached_name}"], Comment.new(id: 1, body: 'ZOMG A COMMENT').attributes
|
||||
assert_equal cached_attributes["#{@comment.post.cache_key}/#{attributes.cached_name}"], Post.new(id: 'post', title: 'New Post', body: 'Body').attributes
|
||||
assert_equal cached_attributes["#{@comment.cache_key}/#{attributes.cache_key}"], Comment.new(id: 1, body: 'ZOMG A COMMENT').attributes
|
||||
assert_equal cached_attributes["#{@comment.post.cache_key}/#{attributes.cache_key}"], Post.new(id: 'post', title: 'New Post', body: 'Body').attributes
|
||||
|
||||
writer = @comment.post.blog.writer
|
||||
writer_cache_key = writer.cache_key
|
||||
|
||||
assert_equal cached_attributes["#{writer_cache_key}/#{attributes.cached_name}"], Author.new(id: 'author', name: 'Joao M. D. Moura').attributes
|
||||
assert_equal cached_attributes["#{writer_cache_key}/#{attributes.cache_key}"], Author.new(id: 'author', name: 'Joao M. D. Moura').attributes
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user