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) }