lib/alba.rb in alba-3.3.3 vs lib/alba.rb in alba-3.4.0
- old
+ new
@@ -40,31 +40,50 @@
end
# Serialize the object with inline definitions
#
# @param object [Object] the object to be serialized
+ # @param with [:inference, Proc, Class<Alba::Resource>] determines how to get resource class for each object
# @param root_key [Symbol, nil, true]
# @param block [Block] resource block
# @return [String] serialized JSON string
# @raise [ArgumentError] if block is absent or `with` argument's type is wrong
- def serialize(object = nil, root_key: nil, &block)
- resource = resource_with(object, &block)
- resource.serialize(root_key: root_key)
+ def serialize(object = nil, with: :inference, root_key: nil, &block)
+ if collection?(object)
+ h = hashify_collection(object, with, &block)
+ Alba.encoder.call(h)
+ else
+ resource = resource_with(object, &block)
+ resource.serialize(root_key: root_key)
+ end
end
# Hashify the object with inline definitions
#
# @param object [Object] the object to be serialized
+ # @param with [:inference, Proc, Class<Alba::Resource>] determines how to get resource class for each object
# @param root_key [Symbol, nil, true]
# @param block [Block] resource block
# @return [String] serialized JSON string
# @raise [ArgumentError] if block is absent or `with` argument's type is wrong
- def hashify(object = nil, root_key: nil, &block)
- resource = resource_with(object, &block)
- resource.as_json(root_key: root_key)
+ def hashify(object = nil, with: :inference, root_key: nil, &block)
+ if collection?(object)
+ hashify_collection(object, with, &block)
+ else
+ resource = resource_with(object, &block)
+ resource.as_json(root_key: root_key)
+ end
end
+ # Detect if object is a collection or not.
+ # When object is a Struct, it's Enumerable but not a collection
+ #
+ # @api private
+ def collection?(object)
+ object.is_a?(Enumerable) && !object.is_a?(Struct)
+ end
+
# Enable inference for key and resource name
#
# @param with [Symbol, Class, Module] inflector
# When it's a Symbol, it sets inflector with given name
# When it's a Class or a Module, it sets given object to inflector
@@ -190,11 +209,15 @@
@_on_nil = nil
@types = {}
register_default_types
end
- # This method could be part of public API, but for now it's private
+ # Get a resource object from arguments
+ # If block is given, it creates a resource class with the block
+ # Otherwise, it infers resource class from the object's class name
+ #
+ # @ param object [Object] the object whose class name is used for inferring resource class
def resource_with(object, &block)
klass = block ? resource_class(&block) : infer_resource_class(object.class.name)
klass.new(object)
end
@@ -248,9 +271,27 @@
end
def default_encoder
lambda do |hash|
JSON.generate(hash)
+ end
+ end
+
+ def hashify_collection(collection, with, &block) # rubocop:disable Metrics/MethodLength
+ collection.map do |obj|
+ resource = if block
+ resource_class(&block)
+ else
+ case with
+ when Class then with
+ when :inference then infer_resource_class(obj.class.name)
+ when Proc then with.call(obj)
+ else raise ArgumentError, '`with` argument must be either :inference, Proc or Class'
+ end
+ end
+ raise Alba::Error if resource.nil?
+
+ resource.new(obj).to_h
end
end
def validate_inflector(inflector)
unless %i[camelize camelize_lower dasherize classify].all? { |m| inflector.respond_to?(m) }