Skip to content
Andrew Geweke edited this page Dec 11, 2013 · 2 revisions

flex_columns lets you "type" fields in flex columns using syntax similar to that for a database column in a migration. Under the covers, this does nothing more (or less) than declaring ActiveModel validations for the fields in question; it's simply a less-verbose, more convenient way of adding validations.

For example, the following code:

class User < ActiveRecord::Base
  flex_column :user_attributes do
    field :desired_emails_per_week, :integer, :null => false
    field :nickname, :string, :limit => 20
    field :last_logged_in_at, :timestamp
    field :is_admin, :boolean, :null => false
    field :background_color, :enum => %w{red blue green}
  end
end

is exactly equivalent to this code:

class User < ActiveRecord::Base
  flex_column :user_attributes do
    field :desired_emails_per_week
    field :nickname
    field :last_logged_in_at
    field :is_admin
  end

  validates :desired_emails_per_week, :numericality => { :only_integer => true }
  validates :desired_emails_per_week, :presence => true
  validates_each :nickname do |record, attr, value|
    record.errors.add(attr, "must be a String") if value && (! value.kind_of?(String)) && (! value.kind_of?(Symbol))
  end
  validates :nickname, :length => { :maximum => 20 }
  validates_each :last_logged_in_at do |record, attr, value|
    record.errors.add(attr, "must be a Time or DateTime") if value && (! value.kind_of?(Time)) && (! value.kind_of?(DateTime))
  end
  validates :is_admin, :presence => true
  validates :is_admin, :inclusion => { :in => [ true, false, nil ] }
  validates :background_color, :inclusion => { :in => [ 'red', 'blue', 'green' ] }
end

(The above example demonstrates all of the shorthand available, except for the additional types of text, float, decimal, date, time, and datetime.)

Perhaps obviously, enum is not a built-in ActiveRecord column type, but it's so common and so widely used that it made sense to create shorthand for it.

Note that because this is using ActiveModel validations, types will never be exactly the same as the corresponding database types. For example, databases will check the range of integers, while the validations above allow any integer; databases will check that a string can be encoded using whatever encoding the string column uses, while the validations above allow any Ruby String. However, it's still a very useful mechanism and lets you compactly constrain your data.

Clone this wiki locally