class Foraneus

Foraneus base class used to declare a data set, aka ‘form’.

Constants

Error

Public Class Methods

accessors() click to toggle source

Return the names of data and error accessors

Returned hash contains the keys :data and :errors, where values are the proper accesor names

@return [Hash]

# File lib/foraneus.rb, line 122
def self.accessors
  @accessors ||= {
    :data => :data,
    :errors => :errors
  }
end
boolean(name, *args) click to toggle source

Declares a boolean field.

@param [Symbol] name The name of the field.

# File lib/foraneus.rb, line 31
def self.boolean(name, *args)
  converter = Foraneus::Converters::Boolean.new(*args)
  field(name, converter)
end
create_instance() click to toggle source

Create a new instance while setting up data and error accessors

@return [Foraneus]

# File lib/foraneus.rb, line 132
def self.create_instance
  instance = self.new

  Utils.singleton_attr_accessor(instance, :data, {})
  Utils.singleton_attr_accessor(instance, :errors, {})

  instance
end
date(name, *args) click to toggle source

Declares a date field.

@param [Symbol] name The name of the field. @param (see Foraneus::Converters::Date#initialize)

# File lib/foraneus.rb, line 40
def self.date(name, *args)
  converter = Foraneus::Converters::Date.new(*args)
  field(name, converter)
end
decimal(name, *args) click to toggle source

Declares a decimal field.

@param [Symbol] name The name of the field. @param (see Foraneus::Converters::Decimal#initialize)

# File lib/foraneus.rb, line 49
def self.decimal(name, *args)
  converter = Foraneus::Converters::Decimal.new(*args)
  field(name, converter)
end
field(name, converter = nil) click to toggle source

Declares a field.

When no converter is given, noop is assigned.

@param [Symbol] name The name of the field. @param [#parse, raw] converter The converter.

# File lib/foraneus.rb, line 103
def self.field(name, converter = nil)
  converter ||= Foraneus::Converters::Noop.new

  fields[name.to_s] = converter
  self.send(:attr_accessor, name)
end
fields() click to toggle source

Map of fields and their corresponding converters.

@return [Hash<String, Converter>]

# File lib/foraneus.rb, line 113
def self.fields
  @fields ||= {}
end
float(name, *args) click to toggle source

Declares a float field.

@param [Symbol] name The name of the field. @param (see Foraneus::Converters::Float#initialize)

# File lib/foraneus.rb, line 58
def self.float(name, *args)
  converter = Foraneus::Converters::Float.new(*args)
  field(name, converter)
end
form(name, &block) click to toggle source

Declares a nested form field

@param [Symbol] name The name of the field. @yield Yields to a nested foraneus spec.

# File lib/foraneus.rb, line 67
def self.form(name, &block)
  converter = Class.new(Foraneus::Converters::Nested, &block)
  field(name, converter)
end
integer(name, *args) click to toggle source

Declares an integer field.

@param [Symbol] name The name of the field. @param (see Foraneus::Converters::Integer#initialize)

# File lib/foraneus.rb, line 76
def self.integer(name, *args)
  converter = Foraneus::Converters::Integer.new(*args)
  field(name, converter)
end
new() click to toggle source

@api private

# File lib/foraneus.rb, line 24
def initialize
  @_ = {} # Hash that holds external representation data
end
noop(name, *args) click to toggle source

Declares a noop field.

@param [Symbol] name The name of the field.

# File lib/foraneus.rb, line 84
def self.noop(name, *args)
  converter = Foraneus::Converters::Noop.new(*args)
  field(name, converter)
end
parse(data = {}) click to toggle source

Parses data coming from an external source.

@param [Hash<Symbol, String>] data External data.

@return [Foraneus] An instance of a form.

# File lib/foraneus.rb, line 146
def self.parse(data = {})
  instance = self.create_instance
  data = data.dup

  instance.instance_variable_set(:@_, data.dup)

  fields.each do |field, converter|
    __parse_field(data, field, converter, instance)
  end

  instance
end
raw(data = {}) click to toggle source

Converts data into an external representation.

@param [Hash<Symbol, Object>] data

@return [Foraneus] An instance of a form.

# File lib/foraneus.rb, line 164
def self.raw(data = {})
  instance = self.create_instance
  data = data.dup

  instance.send("#{self.accessors[:data]}=", data)

  fields.each do |field, converter|
    __raw_field(data, field, converter, instance)
  end

  instance
end
string(name, *args) click to toggle source

Declares a string field.

@param [Symbol] name The name of the field.

# File lib/foraneus.rb, line 92
def self.string(name, *args)
  converter = Foraneus::Converters::String.new(*args)
  field(name, converter)
end

Private Class Methods

__parse_field(data, field, converter, instance) click to toggle source
# File lib/foraneus.rb, line 205
def self.__parse_field(data, field, converter, instance)
  s, is_present = Utils.fetch(data, field)

  v, error = Utils.parse_datum(field, s, converter)

  if error.nil? && !v.nil? && Foraneus::Utils.nested_converter?(converter)
    instance.send(self.accessors[:data])[field.to_sym] = v.data if is_present
    instance.send("#{field}=", v)
    unless v.valid?
      error = Foraneus::Error.new('NestedFormError', "Invalid nested form: #{field}")
      instance.send(self.accessors[:errors])[field.to_sym] = error
    end

  elsif error.nil?
    instance.send("#{field}=", v)
    instance.send(self.accessors[:data])[field.to_sym] = v if is_present || converter.opts.include?(:default)
  else
    if Foraneus::Utils.nested_converter?(converter)
      error = Foraneus::Error.new('NestedFormError', "Invalid nested form: #{field}")
      instance.send(self.accessors[:errors])[field.to_sym] = error
    else
      instance.send(self.accessors[:errors])[field.to_sym] = error if error
    end
  end
end
__raw_field(data, field, converter, instance) click to toggle source
# File lib/foraneus.rb, line 232
def self.__raw_field(data, field, converter, instance)
  v, is_present = Utils.fetch(data, field)

  instance.send("#{field}=", v)

  if v.nil?
    v = converter.opts[:default]
  end

  s = Utils.raw_datum(v, converter)

  if Foraneus::Utils.nested_converter?(converter)
    instance.send("#{field}=", s)
  end

  if is_present || converter.opts.include?(:default)
    if Foraneus::Utils.nested_converter?(converter) && !s.nil?
      instance[field.to_sym] = s[]
    else
      instance[field.to_sym] = s
    end
  end
end

Public Instance Methods

[](m = nil) click to toggle source

@return [Hash] raw data when m == nil. @return [Array<Error>] errors when m == :errors. @return [String] raw data value for the field m.

# File lib/foraneus.rb, line 180
def [](m = nil)
  if m.nil?
    @_
  else
    @_.fetch(m.to_s) do
      @_[m.to_sym]
    end
  end
end
[]=(k, v) click to toggle source

@api private

Sets a raw value.

@param [Symbol] k Field name. @param [String] v Raw value.

# File lib/foraneus.rb, line 196
def []=(k, v)
  @_[k] = v
end
valid?() click to toggle source

Returns true if no conversion errors occurred. false otherwise.

# File lib/foraneus.rb, line 201
def valid?
  @errors.empty?
end