module Riveter::Attributes::ClassMethods

Public Instance Methods

attr_array(name, options={}, &block) click to toggle source
# File lib/riveter/attributes.rb, line 182
def attr_array(name, options={}, &block)
  options = {
    :data_type => :integer,
    :validate => true
  }.merge(options)
  data_type = options.delete(:data_type)

  converter = block_given? ? block : Converters.converter_for(data_type)

  define_method name do
    array = instance_variable_get("@#{name}") || []
    array.map {|v| converter.call(v, options) }
  end

  attr_writer name

  add_attr(name, :array, converter, options)
end
attr_boolean(name, options={}, &block) click to toggle source
# File lib/riveter/attributes.rb, line 143
def attr_boolean(name, options={}, &block)
  options = {
    :validate => true
  }.merge(options)

  converter = block_given? ? block : Converters.converter_for(:boolean)

  attr_reader_with_converter name, converter, options
  alias_method "#{name}?", name

  attr_writer name

  add_attr(name, :boolean, converter, options)
end
attr_class(name, classes, options={}, &block) click to toggle source
# File lib/riveter/attributes.rb, line 234
def attr_class(name, classes, options={}, &block)
  options = {
    :validate => true,
    :classes => classes
  }.merge(options)

  required = options[:required] == true
  converter = block_given? ? block : Converters.converter_for(:class, options)

  attr_reader_with_converter name, converter, options

  validates name,
            :allow_blank => !required,
            :allow_nil => !required,
            :inclusion => { :in => classes } if options[:validate]

  attr_writer name

  add_attr(name, :class, converter, options)
end
attr_date(name, options={}, &block) click to toggle source
# File lib/riveter/attributes.rb, line 51
def attr_date(name, options={}, &block)
  attr_date_or_time(:date, name, options, &block)
end
attr_date_range(name, options={}, &block) click to toggle source
# File lib/riveter/attributes.rb, line 61
def attr_date_range(name, options={}, &block)
  options = {
    :validate => true
  }.merge(options)

  required = (true == options.delete(:required))

  [:min, :max].each do |limit|
    limit_value = options.delete(limit)

    define_method :"#{name}_#{limit}" do
      instance_variable_get("@#{name}_#{limit}") ||
        (limit_value.respond_to?(:call) ? instance_exec(&limit_value) : limit_value)
    end

    # can manually assign the min/max
    define_method :"#{name}_#{limit}=" do |value|
      instance_variable_set("@#{name}_#{limit}", value)
    end

  end

  converter = block_given? ? block : Converters.converter_for(:date)

  # return from and to as range
  define_method name do
    # can't have range starting or ending with nil, so return nil
    send(:"#{name}_from")..send(:"#{name}_to") rescue nil
  end

  define_method :"#{name}=" do |value|
    value ||= nil..nil
    range = value.is_a?(Range) ? value : value..value
    send(:"#{name}_from=", range.first)
    send(:"#{name}_to=", range.last)
  end

  add_attr(name, :date_range, converter, options)

  if options[:validate]

    validate :"#{name}_validation"

    define_method :"#{name}_validation" do
      date_from = send(:"#{name}_from")
      date_to = send(:"#{name}_to")

      errors.add(name, :blank) if
        required && (date_from.blank? || date_to.blank?)

      errors.add(name, :invalid) if
        !(date_from.blank? || date_to.blank?) && (date_from > date_to || date_to < date_from)
    end

  end

  # break down into parts
  [:from, :to].each do |part|
    attr_reader_with_converter :"#{name}_#{part}", converter, options

    define_method :"#{name}_#{part}?" do
      send(:"#{name}_#{part}").present?
    end

    attr_writer :"#{name}_#{part}"

    validates :"#{name}_#{part}",
              :allow_nil => !required,
              :timeliness => { :type => :date } if options[:validate]

    add_attr(:"#{name}_#{part}", :date, converter)
  end

  # helper for determining if both from and to dates have been provided
  define_method :"#{name}_present?" do
    date_from = send(:"#{name}_from")
    date_to = send(:"#{name}_to")
    date_from && date_to
  end

end
attr_datetime(name, options={}, &block)
Alias for: attr_time
attr_decimal(name, options={}, &block) click to toggle source
# File lib/riveter/attributes.rb, line 47
def attr_decimal(name, options={}, &block)
  attr_numeric(:decimal, name, options, &block)
end
attr_enum(name, enum, options={}, &block) click to toggle source

NB: enum must respond to values

# File lib/riveter/attributes.rb, line 159
def attr_enum(name, enum, options={}, &block)
  raise ArgumentError, 'enum' unless enum && enum.respond_to?(:values)

  options = {
    :enum => enum,
    :validate => true
  }.merge(options)

  required = options[:required] == true
  converter = block_given? ? block : Converters.converter_for(:enum, options)

  attr_reader_with_converter name, converter, options

  validates name,
            :allow_blank => !required,
            :allow_nil => !required,
            :inclusion => { :in => enum.values } if options[:validate]

  attr_writer name

  add_attr(name, :enum, converter, options)
end
attr_hash(name, options={}, &block) click to toggle source
# File lib/riveter/attributes.rb, line 201
def attr_hash(name, options={}, &block)
  options = {
    :data_type => :integer,
    :validate => true
  }.merge(options)
  data_type = options.delete(:data_type)

  converter = block_given? ? block : Converters.converter_for(data_type)

  define_method name do
    hash = instance_variable_get("@#{name}") || {}
    hash.merge(hash) {|k, v| converter.call(v, options) }
  end

  attr_writer name

  add_attr(name, :hash, converter, options)
end
attr_integer(name, options={}, &block) click to toggle source
# File lib/riveter/attributes.rb, line 43
def attr_integer(name, options={}, &block)
  attr_numeric(:integer, name, options, &block)
end
attr_object(name, options={}, &block) click to toggle source
# File lib/riveter/attributes.rb, line 220
def attr_object(name, options={}, &block)
  options = {
    :validate => true
  }.merge(options)

  converter = block_given? ? block : Converters.converter_for(:object, options)

  attr_reader_with_converter name, converter, options

  attr_writer name

  add_attr(name, :object, converter, options)
end
attr_string(name, options={}, &block) click to toggle source
# File lib/riveter/attributes.rb, line 28
def attr_string(name, options={}, &block)
  options = {
    :validate => true
  }.merge(options)

  converter = block_given? ? block : Converters.converter_for(:string)

  attr_reader_with_converter name, converter, options
  attr_writer name

  add_attr(name, :string, converter, options)
end
Also aliased as: attr_text
attr_text(name, options={}, &block)
Alias for: attr_string
attr_time(name, options={}, &block) click to toggle source
# File lib/riveter/attributes.rb, line 55
def attr_time(name, options={}, &block)
  attr_date_or_time(:time, name, options, &block)
end
Also aliased as: attr_datetime

Private Instance Methods

add_attr(name, type, converter=nil, options={}) click to toggle source
# File lib/riveter/attributes.rb, line 303
def add_attr(name, type, converter=nil, options={})
  self._attributes[name] = attribute_info = AttributeInfo.new(self, name, type, converter, options)
  validates name, :presence => true if attribute_info.required?
  attribute_info
end
attr_date_or_time(type, name, options={}, &block) click to toggle source
# File lib/riveter/attributes.rb, line 283
def attr_date_or_time(type, name, options={}, &block)
  options = {
    :validate => true
  }.merge(options)

  required = options[:required] == true
  converter = block_given? ? block : Converters.converter_for(type)

  attr_reader_with_converter name, converter, options

  validates name,
            :allow_blank => !required,
            :allow_nil => !required,
            :timeliness => { :type => type } if options[:validate]

  attr_writer name

  add_attr(name, type, converter, options)
end
attr_numeric(type, name, options={}, &block) click to toggle source
# File lib/riveter/attributes.rb, line 263
def attr_numeric(type, name, options={}, &block)
  options = {
    :validate => true
  }.merge(options)

  required = options[:required] == true
  converter = block_given? ? block : Converters.converter_for(type)

  attr_reader_with_converter name, converter, options

  validates name,
            :allow_blank => !required,
            :allow_nil => !required,
            :numericality => { :only => type } if options[:validate]

  attr_writer name

  add_attr(name, type, converter, options)
end
attr_reader_with_converter(name, converter, options={}) click to toggle source
# File lib/riveter/attributes.rb, line 257
def attr_reader_with_converter(name, converter, options={})
  define_method name do
    converter.call(instance_variable_get("@#{name}"), options)
  end
end