module Cistern::Attributes::ClassMethods

Public Instance Methods

aliases() click to toggle source
# File lib/cistern/attributes.rb, line 40
def aliases
  @aliases ||= Hash.new { |h, k| h[k] = [] }
end
attribute(name, options = {}) click to toggle source
# File lib/cistern/attributes.rb, line 48
def attribute(name, options = {})
  name_sym = name.to_sym

  if attributes.key?(name_sym)
    fail(ArgumentError, "#{self.name} attribute[#{name_sym}] specified more than once")
  end

  add_coverage(options)

  normalize_options(options)

  attributes[name_sym] = options

  define_attribute_reader(name_sym, options) unless options[:reader] == false
  define_attribute_writer(name_sym, options) unless options[:writer] == false

  name_sym
end
attributes() click to toggle source
# File lib/cistern/attributes.rb, line 44
def attributes
  @attributes ||= parent_attributes || {}
end
default_parser() click to toggle source
# File lib/cistern/attributes.rb, line 36
def default_parser
  @default_parser ||= ->(v, _opts) { v }
end
identity(*args) click to toggle source
# File lib/cistern/attributes.rb, line 67
def identity(*args)
  args.any? ? @identity = attribute(*args) : (@identity ||= parent_identity)
end
ignore_attributes(*args) click to toggle source
# File lib/cistern/attributes.rb, line 71
def ignore_attributes(*args)
  @ignored_attributes = args
end
ignored_attributes() click to toggle source
# File lib/cistern/attributes.rb, line 75
def ignored_attributes
  @ignored_attributes ||= []
end
parsers() click to toggle source
# File lib/cistern/attributes.rb, line 8
def parsers
  @parsers ||= {
    array:   ->(v, _) { [*v] },
    boolean: ->(v, _) { TRUTHY.include?(v.to_s.downcase) },
    date:    ->(v, _) { v.is_a?(Date) ? v : v && Date.parse(v.to_s) },
    float:   ->(v, _) { v && v.to_f },
    integer: ->(v, _) { v && v.to_i },
    string:  ->(v, _) { v && v.to_s },
    time:    ->(v, _) { v.is_a?(Time) ? v : v && Time.parse(v.to_s) },
  }
end
squasher(tree, path) click to toggle source
# File lib/cistern/attributes.rb, line 20
def squasher(tree, path)
  tree.is_a?(::Hash) ? squasher(tree[path.shift], path) : tree
end
transforms() click to toggle source
# File lib/cistern/attributes.rb, line 24
def transforms
  @transforms ||= {
    squash: proc do |_, _v, options|
      v      = Cistern::Hash.stringify_keys(_v)
      squash = options[:squash]

      v.is_a?(::Hash) ? squasher(v, squash.dup) : v
    end,
    none: ->(_, v, _) { v }
  }
end

Protected Instance Methods

add_coverage(options) click to toggle source
# File lib/cistern/attributes.rb, line 81
def add_coverage(options)
  return unless defined? Cistern::Coverage

  attribute_call = Cistern::Coverage.find_caller_before('cistern/attributes.rb')

  # Only use DSL attribute calls from within a model
  if attribute_call && attribute_call.label.start_with?('<class:')
    options[:coverage_file] = attribute_call.absolute_path
    options[:coverage_line] = attribute_call.lineno
    options[:coverage_hits] = 0
  end
end
define_attribute_reader(name, options) click to toggle source
# File lib/cistern/attributes.rb, line 94
def define_attribute_reader(name, options)
  send(:define_method, name) do
    read_attribute(name)
  end unless instance_methods.include?(name)

  send(:alias_method, "#{name}?", name) if options[:type] == :boolean

  options[:aliases].each { |new_alias| aliases[new_alias] << name }
end
define_attribute_writer(name, options) click to toggle source
# File lib/cistern/attributes.rb, line 104
def define_attribute_writer(name, options)
  return if instance_methods.include?("#{name}=".to_sym)

  send(:define_method, "#{name}=") { |value| write_attribute(name, value) }
end

Private Instance Methods

normalize_options(options) click to toggle source
# File lib/cistern/attributes.rb, line 112
def normalize_options(options)
  options[:squash] = Array(options[:squash]).map(&:to_s) if options[:squash]
  options[:aliases] = Array(options[:aliases] || options[:alias]).map { |a| a.to_sym }

  transform = options.key?(:squash) ? :squash : :none
  options[:transform] ||= transforms.fetch(transform)
  options[:parser] ||= parsers[options[:type]] || default_parser
end
parent_attributes() click to toggle source
# File lib/cistern/attributes.rb, line 121
def parent_attributes
  superclass && superclass.respond_to?(:attributes) && superclass.attributes.dup
end
parent_identity() click to toggle source
# File lib/cistern/attributes.rb, line 125
def parent_identity
  superclass && superclass.respond_to?(:identity) && superclass.identity
end