mirror of
https://github.com/ditkrg/active_model_serializers.git
synced 2026-01-25 07:16:49 +00:00
Merge remote-tracking branch 'upstream/master' into fix-jsonapi-ri
This commit is contained in:
@@ -15,7 +15,7 @@ module ActiveModel
|
||||
end
|
||||
|
||||
def self.adapter_class(adapter)
|
||||
adapter_name = adapter.to_s.classify.sub("API", "Api")
|
||||
adapter_name = adapter.to_s.classify.sub('API', 'Api')
|
||||
"ActiveModel::Serializer::Adapter::#{adapter_name}".safe_constantize
|
||||
end
|
||||
|
||||
@@ -68,12 +68,12 @@ module ActiveModel
|
||||
parts = []
|
||||
parts << object_cache_key
|
||||
parts << @klass._cache_digest unless @klass._cache_options && @klass._cache_options[:skip_digest]
|
||||
parts.join("/")
|
||||
parts.join('/')
|
||||
end
|
||||
|
||||
def object_cache_key
|
||||
object_time_safe = @cached_serializer.object.updated_at
|
||||
object_time_safe = object_time_safe.strftime("%Y%m%d%H%M%S%9N") if object_time_safe.respond_to?(:strftime)
|
||||
object_time_safe = object_time_safe.strftime('%Y%m%d%H%M%S%9N') if object_time_safe.respond_to?(:strftime)
|
||||
(@klass._cache_key) ? "#{@klass._cache_key}/#{@cached_serializer.object.id}-#{object_time_safe}" : @cached_serializer.object.cache_key
|
||||
end
|
||||
|
||||
@@ -82,7 +82,7 @@ module ActiveModel
|
||||
end
|
||||
|
||||
def meta_key
|
||||
serializer.meta_key || "meta"
|
||||
serializer.meta_key || 'meta'
|
||||
end
|
||||
|
||||
def root
|
||||
|
||||
@@ -2,7 +2,6 @@ module ActiveModel
|
||||
class Serializer
|
||||
class Adapter
|
||||
class FragmentCache
|
||||
|
||||
attr_reader :serializer
|
||||
|
||||
def initialize(adapter, serializer, options)
|
||||
@@ -35,7 +34,7 @@ module ActiveModel
|
||||
|
||||
def cached_attributes(klass, serializers)
|
||||
attributes = serializer.class._attributes
|
||||
cached_attributes = (klass._cache_only) ? klass._cache_only : attributes.reject {|attr| klass._cache_except.include?(attr) }
|
||||
cached_attributes = (klass._cache_only) ? klass._cache_only : attributes.reject { |attr| klass._cache_except.include?(attr) }
|
||||
non_cached_attributes = attributes - cached_attributes
|
||||
|
||||
cached_attributes.each do |attribute|
|
||||
@@ -60,7 +59,7 @@ module ActiveModel
|
||||
Object.const_set cached, Class.new(ActiveModel::Serializer) unless Object.const_defined?(cached)
|
||||
Object.const_set non_cached, Class.new(ActiveModel::Serializer) unless Object.const_defined?(non_cached)
|
||||
|
||||
klass._cache_options ||= {}
|
||||
klass._cache_options ||= {}
|
||||
klass._cache_options[:key] = klass._cache_key if klass._cache_key
|
||||
|
||||
cached.constantize.cache(klass._cache_options)
|
||||
@@ -68,7 +67,7 @@ module ActiveModel
|
||||
cached.constantize.fragmented(serializer)
|
||||
non_cached.constantize.fragmented(serializer)
|
||||
|
||||
serializers = {cached: cached, non_cached: non_cached}
|
||||
serializers = { cached: cached, non_cached: non_cached }
|
||||
cached_attributes(klass, serializers)
|
||||
serializers
|
||||
end
|
||||
|
||||
@@ -46,7 +46,6 @@ module ActiveModel
|
||||
def fragment_cache(cached_hash, non_cached_hash)
|
||||
Json::FragmentCache.new().fragment_cache(cached_hash, non_cached_hash)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,11 +4,9 @@ module ActiveModel
|
||||
class Adapter
|
||||
class Json < Adapter
|
||||
class FragmentCache
|
||||
|
||||
def fragment_cache(cached_hash, non_cached_hash)
|
||||
non_cached_hash.merge cached_hash
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -159,19 +159,21 @@ module ActiveModel
|
||||
|
||||
def add_links(options)
|
||||
links = @hash.fetch(:links) { {} }
|
||||
resources = serializer.instance_variable_get(:@resource)
|
||||
@hash[:links] = add_pagination_links(links, resources, options) if is_paginated?(resources)
|
||||
collection = serializer.object
|
||||
if is_paginated?(collection)
|
||||
@hash[:links] = add_pagination_links(links, collection, options)
|
||||
end
|
||||
end
|
||||
|
||||
def add_pagination_links(links, resources, options)
|
||||
pagination_links = JsonApi::PaginationLinks.new(resources, options[:context]).serializable_hash(options)
|
||||
def add_pagination_links(links, collection, options)
|
||||
pagination_links = JsonApi::PaginationLinks.new(collection, options[:context]).serializable_hash(options)
|
||||
links.update(pagination_links)
|
||||
end
|
||||
|
||||
def is_paginated?(resource)
|
||||
resource.respond_to?(:current_page) &&
|
||||
resource.respond_to?(:total_pages) &&
|
||||
resource.respond_to?(:size)
|
||||
def is_paginated?(collection)
|
||||
collection.respond_to?(:current_page) &&
|
||||
collection.respond_to?(:total_pages) &&
|
||||
collection.respond_to?(:size)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,19 +4,17 @@ module ActiveModel
|
||||
class Adapter
|
||||
class JsonApi < Adapter
|
||||
class FragmentCache
|
||||
|
||||
def fragment_cache(root, cached_hash, non_cached_hash)
|
||||
hash = {}
|
||||
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] }
|
||||
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
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,23 +3,22 @@ module ActiveModel
|
||||
class ArraySerializer
|
||||
NoSerializerError = Class.new(StandardError)
|
||||
include Enumerable
|
||||
delegate :each, to: :@objects
|
||||
delegate :each, to: :@serializers
|
||||
|
||||
attr_reader :root, :meta, :meta_key
|
||||
attr_reader :object, :root, :meta, :meta_key
|
||||
|
||||
def initialize(objects, options = {})
|
||||
def initialize(resources, options = {})
|
||||
@root = options[:root]
|
||||
@resource = objects
|
||||
@objects = objects.map do |object|
|
||||
serializer_class = options.fetch(
|
||||
:serializer,
|
||||
ActiveModel::Serializer.serializer_for(object)
|
||||
)
|
||||
@object = resources
|
||||
@serializers = resources.map do |resource|
|
||||
serializer_class = options.fetch(:serializer) {
|
||||
ActiveModel::Serializer.serializer_for(resource)
|
||||
}
|
||||
|
||||
if serializer_class.nil?
|
||||
fail NoSerializerError, "No serializer found for object: #{object.inspect}"
|
||||
fail NoSerializerError, "No serializer found for resource: #{resource.inspect}"
|
||||
else
|
||||
serializer_class.new(object, options.except(:serializer))
|
||||
serializer_class.new(resource, options.except(:serializer))
|
||||
end
|
||||
end
|
||||
@meta = options[:meta]
|
||||
@@ -27,7 +26,7 @@ module ActiveModel
|
||||
end
|
||||
|
||||
def json_key
|
||||
key = root || @objects.first.try(:json_key) || @resource.try(:name).try(:underscore)
|
||||
key = root || @serializers.first.try(:json_key) || object.try(:name).try(:underscore)
|
||||
key.try(:pluralize)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,10 +7,9 @@ module ActiveModel
|
||||
# @param [Hash{Symbol => Object}] options
|
||||
#
|
||||
# @example
|
||||
# Association.new(:comments, CommentSummarySerializer, embed: :ids)
|
||||
# Association.new(:comments, CommentSummarySerializer)
|
||||
#
|
||||
Association = Struct.new(:name, :serializer, :options) do
|
||||
|
||||
# @return [Symbol]
|
||||
#
|
||||
def key
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
module ActiveModel
|
||||
class Serializer
|
||||
class Fieldset
|
||||
|
||||
def initialize(fields, root = nil)
|
||||
@root = root
|
||||
@raw_fields = fields
|
||||
@@ -16,7 +15,7 @@ module ActiveModel
|
||||
fields[key.to_sym] || fields[key.pluralize.to_sym]
|
||||
end
|
||||
|
||||
private
|
||||
private
|
||||
|
||||
ActiveModelSerializers.silence_warnings do
|
||||
attr_reader :raw_fields, :root
|
||||
@@ -24,7 +23,7 @@ module ActiveModel
|
||||
|
||||
def parsed_fields
|
||||
if raw_fields.is_a?(Hash)
|
||||
raw_fields.inject({}) { |h,(k,v)| h[k.to_sym] = v.map(&:to_sym); h}
|
||||
raw_fields.inject({}) { |h, (k, v)| h[k.to_sym] = v.map(&:to_sym); h }
|
||||
elsif raw_fields.is_a?(Array)
|
||||
if root.nil?
|
||||
raise ArgumentError, 'The root argument must be specified if the fileds argument is an array.'
|
||||
@@ -36,7 +35,6 @@ module ActiveModel
|
||||
{}
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15,7 +15,6 @@ module ActiveModel::Serializer::Lint
|
||||
# always return +{}+, and the tests would pass. It is up to you to ensure
|
||||
# that the values are semantically meaningful.
|
||||
module Tests
|
||||
|
||||
# Passes if the object responds to <tt>serializable_hash</tt> and if it takes
|
||||
# zero or one arguments.
|
||||
# Fails otherwise.
|
||||
@@ -23,7 +22,7 @@ module ActiveModel::Serializer::Lint
|
||||
# <tt>serializable_hash</tt> returns a hash representation of a object's attributes.
|
||||
# Typically, it is implemented by including ActiveModel::Serialization.
|
||||
def test_serializable_hash
|
||||
assert_respond_to resource, :serializable_hash, "The resource should respond to serializable_hash"
|
||||
assert_respond_to resource, :serializable_hash, 'The resource should respond to serializable_hash'
|
||||
resource.serializable_hash
|
||||
resource.serializable_hash(nil)
|
||||
end
|
||||
@@ -35,8 +34,18 @@ module ActiveModel::Serializer::Lint
|
||||
# <tt>read_attribute_for_serialization</tt> gets the attribute value for serialization
|
||||
# Typically, it is implemented by including ActiveModel::Serialization.
|
||||
def test_read_attribute_for_serialization
|
||||
assert_respond_to resource, :read_attribute_for_serialization, "The resource should respond to read_attribute_for_serialization"
|
||||
assert_equal resource.method(:read_attribute_for_serialization).arity, 1
|
||||
assert_respond_to resource, :read_attribute_for_serialization, 'The resource should respond to read_attribute_for_serialization'
|
||||
actual_arity = resource.method(:read_attribute_for_serialization).arity
|
||||
if defined?(::Rubinius)
|
||||
# 1 for def read_attribute_for_serialization(name); end
|
||||
# -2 for alias :read_attribute_for_serialization :send for rbx because :shrug:
|
||||
assert_includes [1, -2], actual_arity, "expected #{actual_arity.inspect} to be 1 or -2"
|
||||
else
|
||||
# using absolute value since arity is:
|
||||
# 1 for def read_attribute_for_serialization(name); end
|
||||
# -1 for alias :read_attribute_for_serialization :send
|
||||
assert_includes [1, -1], actual_arity, "expected #{actual_arity.inspect} to be 1 or -1"
|
||||
end
|
||||
end
|
||||
|
||||
# Passes if the object responds to <tt>as_json</tt> and if it takes
|
||||
@@ -68,7 +77,7 @@ module ActiveModel::Serializer::Lint
|
||||
end
|
||||
|
||||
# Passes if the object responds to <tt>cache_key</tt> and if it takes no
|
||||
# arguments.
|
||||
# arguments (Rails 4.0) or a splat (Rails 4.1+).
|
||||
# Fails otherwise.
|
||||
#
|
||||
# <tt>cache_key</tt> returns a (self-expiring) unique key for the object,
|
||||
@@ -76,7 +85,11 @@ module ActiveModel::Serializer::Lint
|
||||
# It is not required unless caching is enabled.
|
||||
def test_cache_key
|
||||
assert_respond_to resource, :cache_key
|
||||
assert_equal resource.method(:cache_key).arity, 0
|
||||
actual_arity = resource.method(:cache_key).arity
|
||||
# using absolute value since arity is:
|
||||
# 0 for Rails 4.1+, *timestamp_names
|
||||
# -1 for Rails 4.0, no arguments
|
||||
assert_includes [-1, 0], actual_arity, "expected #{actual_arity.inspect} to be 0 or -1"
|
||||
end
|
||||
|
||||
# Passes if the object responds to <tt>id</tt> and if it takes no
|
||||
@@ -112,6 +125,5 @@ module ActiveModel::Serializer::Lint
|
||||
def assert_instance_of(result, name)
|
||||
assert result.instance_of?(name), "#{result} should be an instance of #{name}"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
module ActiveModel
|
||||
class Serializer
|
||||
VERSION = "0.10.0.rc2"
|
||||
VERSION = '0.10.0.rc2'
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user