Skip to content

Commit

Permalink
Add comments with YARD syntax
Browse files Browse the repository at this point in the history
The only one code change is to add `to_sym`.
  • Loading branch information
okuramasafumi committed Aug 28, 2020
1 parent 1498622 commit 5d6838e
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 1 deletion.
15 changes: 15 additions & 0 deletions lib/alba.rb
Expand Up @@ -4,18 +4,33 @@

# Core module
module Alba
# Base class for Errors
class Error < StandardError; end
# Error class for backend which is not supported
class UnsupportedBackend < Error; end

class << self
attr_reader :backend, :encoder
attr_accessor :default_serializer

# Set the backend, which actually serializes object into JSON
#
# @param backend [#to_sym, nil] the name of the backend
# Possible values are `oj`, `active_support`, `default`, `json` and nil
# @return [Proc] the proc to encode object into JSON
# @raise [Alba::UnsupportedBackend] if backend is not supported
def backend=(backend)
@backend = backend&.to_sym
set_encoder
end

# Serialize the object with inline definitions
#
# @param object [Object] the object to be serialized
# @param with [nil, Proc, Alba::Serializer] selializer
# @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, with: nil, &block)
raise ArgumentError, 'Block required' unless block

Expand Down
5 changes: 5 additions & 0 deletions lib/alba/association.rb
Expand Up @@ -2,6 +2,10 @@ module Alba
# Base class for `One` and `Many`
# Child class should implement `to_hash` method
class Association
# @param name [Symbol] name of the method to fetch association
# @param condition [Proc] a proc filtering data
# @param resource [Class<Alba::Resource>] a resource class for the association
# @param block [Block] used to define resource when resource arg is absent
def initialize(name:, condition: nil, resource: nil, &block)
@name = name
@condition = condition
Expand All @@ -10,6 +14,7 @@ def initialize(name:, condition: nil, resource: nil, &block)
raise ArgumentError, 'resource or block is required' if @resource.nil? && @block.nil?
end

# @abstract
def to_hash
:not_implemented
end
Expand Down
5 changes: 5 additions & 0 deletions lib/alba/many.rb
Expand Up @@ -3,6 +3,11 @@
module Alba
# Representing many association
class Many < Association
# Recursively converts objects into an Array of Hashes
#
# @param target [Object] the object having an association method
# @param params [Hash] user-given Hash for arbitrary data
# @return [Array<Hash>]
def to_hash(target, params: {})
objects = target.public_send(@name)
objects = @condition.call(objects, params) if @condition
Expand Down
5 changes: 5 additions & 0 deletions lib/alba/one.rb
Expand Up @@ -3,6 +3,11 @@
module Alba
# Representing one association
class One < Association
# Recursively converts an object into a Hash
#
# @param target [Object] the object having an association method
# @param params [Hash] user-given Hash for arbitrary data
# @return [Hash]
def to_hash(target, params: {})
object = target.public_send(@name)
object = @condition.call(object, params) if @condition
Expand Down
49 changes: 49 additions & 0 deletions lib/alba/resource.rb
Expand Up @@ -5,7 +5,12 @@
module Alba
# This module represents what should be serialized
module Resource
# @!parse include InstanceMethods
# @!parse extend ClassMethods
DSLS = {_attributes: {}, _serializer: nil, _key: nil}.freeze
private_constant :DSLS

# @private
def self.included(base)
super
base.class_eval do
Expand All @@ -22,12 +27,18 @@ def self.included(base)
module InstanceMethods
attr_reader :object, :_key, :params

# @param object [Object] the object to be serialized
# @param params [Hash] user-given Hash for arbitrary data
def initialize(object, params: {})
@object = object
@params = params
DSLS.each_key { |name| instance_variable_set("@#{name}", self.class.public_send(name)) }
end

# Get serializer with `with` argument and serialize self with it
#
# @param with [nil, Proc, Alba::Serializer] selializer
# @return [String] serialized JSON string
def serialize(with: nil)
serializer = case with
when nil
Expand All @@ -42,11 +53,15 @@ def serialize(with: nil)
serializer.new(self).serialize
end

# A Hash for serialization
#
# @return [Hash]
def serializable_hash
collection? ? @object.map(&converter) : converter.call(@object)
end
alias to_hash serializable_hash

# @return [Symbol]
def key
@_key || self.class.name.delete_suffix('Resource').downcase.gsub(/:{2}/, '_').to_sym
end
Expand Down Expand Up @@ -91,38 +106,72 @@ def collection?
module ClassMethods
attr_reader(*DSLS.keys)

# @private
def inherited(subclass)
super
DSLS.each_key { |name| subclass.instance_variable_set("@#{name}", instance_variable_get("@#{name}").clone) }
end

# Set multiple attributes at once
#
# @param attrs [Array<String, Symbol>]
def attributes(*attrs)
attrs.each { |attr_name| @_attributes[attr_name.to_sym] = attr_name.to_sym }
end

# Set an attribute with the given block
#
# @param name [String, Symbol] key name
# @param block [Block] the block called during serialization
# @raise [ArgumentError] if block is absent
def attribute(name, &block)
raise ArgumentError, 'No block given in attribute method' unless block

@_attributes[name.to_sym] = block
end

# Set One association
#
# @param name [String, Symbol]
# @param condition [Proc]
# @param resource [Class<Alba::Resource>]
# @param key [String, Symbol] used as key when given
# @param block [Block]
# @see Alba::One#initialize
def one(name, condition = nil, resource: nil, key: nil, &block)
@_attributes[key&.to_sym || name.to_sym] = One.new(name: name, condition: condition, resource: resource, &block)
end

# Set Many association
#
# @param name [String, Symbol]
# @param condition [Proc]
# @param resource [Class<Alba::Resource>]
# @param key [String, Symbol] used as key when given
# @param block [Block]
# @see Alba::Many#initialize
def many(name, condition = nil, resource: nil, key: nil, &block)
@_attributes[key&.to_sym || name.to_sym] = Many.new(name: name, condition: condition, resource: resource, &block)
end

# Set serializer for the resource
#
# @param name [Alba::Serializer]
def serializer(name)
@_serializer = name <= Alba::Serializer ? name : nil
end

# Set key
#
# @param key [String, Symbol]
def key(key)
@_key = key.to_sym
end

# Delete attributes
# Use this DSL in child class to ignore certain attributes
#
# @param attributes [Array<String, Symbol>]
def ignoring(*attributes)
attributes.each do |attr_name|
@_attributes.delete(attr_name.to_sym)
Expand Down
18 changes: 17 additions & 1 deletion lib/alba/serializer.rb
@@ -1,6 +1,10 @@
module Alba
# This module represents how a resource should be serialized.
module Serializer
# @!parse include InstanceMethods
# @!parse extend ClassMethods

# @private
def self.included(base)
super
base.class_eval do
Expand All @@ -13,6 +17,7 @@ def self.included(base)

# Instance methods
module InstanceMethods
# @param resource [Alba::Resource]
def initialize(resource)
@resource = resource
@hash = resource.serializable_hash
Expand All @@ -21,6 +26,9 @@ def initialize(resource)
@hash.is_a?(Hash) ? @hash.merge!(metadata.to_h) : @hash << metadata
end

# Use real encoder to actually serialize to JSON
#
# @return [String] JSON string
def serialize
Alba.encoder.call(@hash)
end
Expand All @@ -42,17 +50,25 @@ def metadata
module ClassMethods
attr_reader :_opts, :_metadata

# @private
def inherited(subclass)
super
%w[_opts _metadata].each { |name| subclass.instance_variable_set("@#{name}", public_send(name).clone) }
end

# Set options, currently key only
#
# @param key [Boolean, Symbol]
def set(key: false)
@_opts[:key] = key
end

# Set metadata
#
# @param name [String, Symbol] key for the metadata
# @param block [Block] the content of the metadata
def metadata(name, &block)
@_metadata[name] = block
@_metadata[name.to_sym] = block
end
end
end
Expand Down

0 comments on commit 5d6838e

Please sign in to comment.