module HoboFields

Constants

ALIAS_TYPES
Model
PLAIN_TYPES
STANDARD_TYPES

Provide a lookup for these rather than loading them all preemptively

VERSION

Attributes

field_types[R]

Public Class Methods

acts_as_list_with_field_declaration(options = {}) click to toggle source

Extended version of the acts_as_list declaration that automatically delcares the ‘position’ field

# File lib/hobo_fields/model.rb, line 197
def self.acts_as_list_with_field_declaration(options = {})
  declare_field(options.fetch(:column, "position"), :integer)
  default_scope { order("#{self.table_name}.position ASC") }
  acts_as_list_without_field_declaration(options)
end
add_formatting_for_field(name, type, args) click to toggle source
# File lib/hobo_fields/model.rb, line 171
def self.add_formatting_for_field(name, type, args)
  type_class = HoboFields.to_class(type)
  if type_class && "format".in?(type_class.instance_methods)
    self.before_validation do |record|
      record.send("#{name}=", record.send(name)._?.format)
    end
  end
end
add_index_for_field(name, args, options) click to toggle source
# File lib/hobo_fields/model.rb, line 180
def self.add_index_for_field(name, args, options)
  to_name = options.delete(:index)
  unless to_name
    # passing :unique => true doesn't do anything without an index
    Rails.logger.error('ERROR: passing :unique => true without :index => true does nothing. Use :unique instead.') if options[:unique]
    return
  end
  index_opts = {}
  index_opts[:unique] = :unique.in?(args) || options.delete(:unique)
  # support :index => true declaration
  index_opts[:name] = to_name unless to_name == true
  index(name, index_opts)
end
add_validations_for_field(name, type, args) click to toggle source

Add field validations according to arguments in the field declaration

# File lib/hobo_fields/model.rb, line 156
def self.add_validations_for_field(name, type, args)
  validates_presence_of   name if :required.in?(args)
  validates_uniqueness_of name, :allow_nil => !:required.in?(args) if :unique.in?(args)

  # Support for custom validations in Hobo Fields
  type_class = HoboFields.to_class(type)
  if type_class && type_class.public_method_defined?("validate")
    self.validate do |record|
      v = record.send(name)._?.validate
      record.errors.add(name, v) if v.is_a?(String)
    end
  end

end
attr_type(name) click to toggle source

Returns the type (a class) for a given field or association. If the association is a collection (has_many or habtm) return the AssociationReflection instead

# File lib/hobo_fields/model.rb, line 207
def self.attr_type(name)
  if attr_types.nil? && self != self.name.constantize
    raise RuntimeError, "attr_types called on a stale class object (#{self.name}). Avoid storing persistent references to classes"
  end

  attr_types[name] or

    if (refl = reflections[name.to_s])
      if refl.macro.in?([:has_one, :belongs_to]) && !refl.options[:polymorphic]
        refl.klass
      else
        refl
      end
    end or

    (col = column(name.to_s) and HoboFields::PLAIN_TYPES[col.type] || col.klass)
end
column(name) click to toggle source

Return the entry from columns for the named column

# File lib/hobo_fields/model.rb, line 227
def self.column(name)
  return unless (@table_exists ||= table_exists?)
  name = name.to_s
  columns.find {|c| c.name == name }
end
declare_attr_type(name, type, options={}) click to toggle source

Declare a rich-type for any attribute (i.e. getter method). This does not effect the attribute in any way - it just records the metadata.

# File lib/hobo_fields/model.rb, line 131
def self.declare_attr_type(name, type, options={})
  klass = HoboFields.to_class(type)
  attr_types[name] = HoboFields.to_class(type)
  klass.try.declared(self, name, options)
end
declare_field(name, type, *args) click to toggle source

Declare named field with a type and an arbitrary set of arguments. The arguments are forwarded to the field_added callback, allowing custom metadata to be added to field declarations.

# File lib/hobo_fields/model.rb, line 142
def self.declare_field(name, type, *args)
  options = args.extract_options!
  try.field_added(name, type, args, options)
  add_formatting_for_field(name, type, args)
  add_validations_for_field(name, type, args)
  add_index_for_field(name, args, options)
  declare_attr_type(name, type, options) unless HoboFields.plain_type?(type)
  field_specs[name] = HoboFields::Model::FieldSpec.new(self, name, type, options)
  attr_order << name unless name.in?(attr_order)
end
declare_polymorphic_type_field(name, column_options) click to toggle source

Declares the “foo_type” field that accompanies the “foo_id” field for a polyorphic belongs_to

# File lib/hobo_fields/model.rb, line 119
def self.declare_polymorphic_type_field(name, column_options)
  type_col = "#{name}_type"
  declare_field(type_col, :string, column_options)
  # FIXME: Before hobo_fields was extracted, this used to now do:
  # never_show(type_col)
  # That needs doing somewhere
end
root() click to toggle source
# File lib/hobo_fields.rb, line 15
def self.root; @@root; end

Public Instance Methods

can_wrap?(type, val) click to toggle source
# File lib/hobo_fields.rb, line 66
def can_wrap?(type, val)
  col_type = type::COLUMN_TYPE
  return false if val.blank? && (col_type == :integer || col_type == :float || col_type == :decimal)
  klass = Object.instance_method(:class).bind(val).call # Make sure we get the *real* class
  init_method = type.instance_method(:initialize)
  [-1,1].include?(init_method.arity) &&
    init_method.owner != Object.instance_method(:initialize).owner &&
    !@never_wrap_types.any? { |c| klass <= c }
end
never_wrap(type) click to toggle source
# File lib/hobo_fields.rb, line 76
def never_wrap(type)
  @never_wrap_types << type
end
plain_type?(type_name) click to toggle source
# File lib/hobo_fields.rb, line 84
def plain_type?(type_name)
  type_name.in?(PLAIN_TYPES)
end
register_type(name, klass) click to toggle source
# File lib/hobo_fields.rb, line 80
def register_type(name, klass)
  field_types[name] = klass
end
standard_class(name) click to toggle source
# File lib/hobo_fields.rb, line 88
def standard_class(name)
  class_name = STANDARD_TYPES[name]
  "HoboFields::Types::#{class_name}".constantize if class_name
end
to_class(type) click to toggle source
# File lib/hobo_fields.rb, line 53
def to_class(type)
  if type.is_one_of?(Symbol, String)
    type = type.to_sym
    field_types[type] || standard_class(type)
  else
    type # assume it's already a class
  end
end
to_name(type) click to toggle source
# File lib/hobo_fields.rb, line 62
def to_name(type)
  field_types.key(type) || ALIAS_TYPES[type]
end