class Koine::Attributes::Attributes

Public Class Methods

new(object, adapters:, options: {}) click to toggle source
# File lib/koine/attributes/attributes.rb, line 6
def initialize(object, adapters:, options: {})
  @object = object
  @adapters = adapters
  @values = {}
  @initializer = { strict: true, freeze: false, initialize: !options[:initializer].nil? }

  if options[:initializer].is_a?(Hash)
    @initializer = @initializer.merge(options[:initializer])
  end
end

Public Instance Methods

==(other) click to toggle source
# File lib/koine/attributes/attributes.rb, line 57
def ==(other)
  other.to_h == to_h
end
get(attribute) click to toggle source
# File lib/koine/attributes/attributes.rb, line 53
def get(attribute)
  @values[attribute.to_sym] || adapter_for(attribute).default_value
end
initialize_values(values = {}) click to toggle source
# File lib/koine/attributes/attributes.rb, line 17
def initialize_values(values = {})
  if !@initializer[:initialize] && !values.empty?
    raise InvalidAttributesError, "wrong number of arguments (given #{values.length}, expected 0)"
  end

  return unless @initializer[:initialize]

  set_values(values) && @initializer[:freeze] && freeze
end
method_missing(method_name, *args) click to toggle source
# File lib/koine/attributes/attributes.rb, line 84
def method_missing(method_name, *args)
  unless respond_to?(method_name)
    raise NoMethodError, "Undefined method #{method_name} for attributed object #{@object}"
  end

  method_name = method_name.to_s

  if method_name.to_s =~ /=$/
    attribute = method_name.to_s.delete('=')
    return set(attribute, *args)
  end

  matches = method_name.match(/^with_(.*)$/)
  return with_attribute(matches[1], *args) if matches

  get(method_name)
end
respond_to?(method, _include_private = nil) click to toggle source
# File lib/koine/attributes/attributes.rb, line 67
def respond_to?(method, _include_private = nil)
  method = method.to_s

  # getter
  return true if has_attribute?(method)

  # {attribute_name}=value
  matches = method.match(/^(.*)=$/)
  return has_attribute?(matches[1]) if matches

  # with_{attribute}(value)
  matches = method.match(/^with_(.*)$/)
  return has_attribute?(matches[1]) if matches

  false
end
set(attribute, value) click to toggle source
# File lib/koine/attributes/attributes.rb, line 44
def set(attribute, value)
  @values[attribute.to_sym] = adapter_for(attribute).coerce(value)
end
set_values(values) click to toggle source
# File lib/koine/attributes/attributes.rb, line 27
def set_values(values)
  invalid_attributes = []

  if @initializer[:strict]
    attributes = values.keys.map(&:to_sym)
    invalid_attributes = attributes - valid_attributes
  end

  unless invalid_attributes.empty?
    raise InvalidAttributesError, "Invalid attributes (#{invalid_attributes.join(', ')})"
  end

  values.each do |attribute, value|
    set(attribute, value) if has_attribute?(attribute)
  end
end
to_h() click to toggle source
# File lib/koine/attributes/attributes.rb, line 61
def to_h
  valid_attributes.map do |name|
    [name.to_sym, @object.send(name)]
  end.to_h
end
with_attribute(attribute, value) click to toggle source
# File lib/koine/attributes/attributes.rb, line 48
def with_attribute(attribute, value)
  new_attributes = to_h.merge(attribute => value)
  @object.class.new(new_attributes)
end

Private Instance Methods

adapter_for(attribute) click to toggle source
# File lib/koine/attributes/attributes.rb, line 112
def adapter_for(attribute)
  @adapters.fetch(attribute.to_sym)
end
freeze() click to toggle source
Calls superclass method
# File lib/koine/attributes/attributes.rb, line 116
def freeze
  @object.freeze
  @adapters.freeze
  @values.freeze
  super
end
has_attribute?(attribute) click to toggle source
# File lib/koine/attributes/attributes.rb, line 108
def has_attribute?(attribute)
  @adapters.key?(attribute.to_sym)
end
valid_attributes() click to toggle source
# File lib/koine/attributes/attributes.rb, line 104
def valid_attributes
  @adapters.keys
end