Provide a lookup for these rather than loading them all preemptively
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
# 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
# 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 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
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
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 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 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
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
# File lib/hobo_fields.rb, line 15 def self.root; @@root; end
# 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
# File lib/hobo_fields.rb, line 76 def never_wrap(type) @never_wrap_types << type end
# File lib/hobo_fields.rb, line 84 def plain_type?(type_name) type_name.in?(PLAIN_TYPES) end
# File lib/hobo_fields.rb, line 80 def register_type(name, klass) field_types[name] = klass end
# 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
# 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
# File lib/hobo_fields.rb, line 62 def to_name(type) field_types.key(type) || ALIAS_TYPES[type] end