class ActiveRecord::ConnectionAdapters::TableDefinition

The Columns are stored as a ColumnDefinition in the columns attribute.
The table definitions
end
end

def self.down
end
end
puts t.class # => “ActiveRecord::ConnectionAdapters::TableDefinition”
create_table :foo do |t|
def self.up
class SomeMigration < ActiveRecord::Migration
change_table is actually of this type:
Inside migration files, the t object in create_table and
provides methods for manipulating the schema representation.
Represents the schema of an SQL table in an abstract way. This class

def [](name)

Returns a ColumnDefinition for the column with name +name+.
def [](name)
  @columns.find {|column| column.name.to_s == name.to_s}
end

def column(name, type, options = {})

end
t.references :taggable, :polymorphic => { :default => 'Photo' }
t.references :tagger, :polymorphic => true
t.references :tag
create_table :taggings do |t|

Can also be written as follows using references:

end
t.string :taggable_type, :default => 'Photo'
t.string :tagger_type
t.integer :tag_id, :tagger_id, :taggable_id
create_table :taggings do |t|

used when creating the _type column. So what can be written like this:
column if the :polymorphic option is supplied. If :polymorphic is a hash of options, these will be
TableDefinition#references will add an appropriately-named _id column, plus a corresponding _type

TableDefinition#timestamps that'll add created_at and +updated_at+ as datetimes.
There's a short-hand method for each of the type values declared at the top. And then there's

end
t.timestamps
t.string :name, :value, :default => "Untitled"
t.integer :shop_id, :creator_id
create_table :products do |t|

Can also be written as follows using the short-hand:

end
t.column "updated_at", :datetime
t.column "created_at", :datetime
t.column "value", :string, :default => "Untitled"
t.column "name", :string, :default => "Untitled"
t.column "creator_id", :integer
t.column "shop_id", :integer
create_table "products", :force => true do |t|

What can be written like this with the regular calls to column:

in a single statement.
They use the type as the method name instead of as a parameter and allow for multiple columns to be defined
Instead of calling +column+ directly, you can also work with the short-hand definitions for the default types.

== Short-hand examples

# => foo polygon
td.column(:foo, 'polygon')
# Defines a column with a database-specific type.

# => huge_integer DECIMAL(30)
td.column(:huge_integer, :decimal, :precision => 30)
# probably wouldn't hurt to include it.
# While :scale defaults to zero on most databases, it

# => sensor_reading DECIMAL(30,20)
td.column(:sensor_reading, :decimal, :precision => 30, :scale => 20)

# => bill_gates_money DECIMAL(15,2)
td.column(:bill_gates_money, :decimal, :precision => 15, :scale => 2)

# => sales_stage VARCHAR(20) DEFAULT 'new' NOT NULL
td.column(:sales_stage, :string, :limit => 20, :default => 'new', :null => false)

# => picture BLOB(2097152)
td.column(:picture, :binary, :limit => 2.megabytes)

# granted BOOLEAN
td.column(:granted, :boolean)
# Assuming td is an instance of TableDefinition
== Examples

This method returns self.

* OpenBase?: Documentation unclear. Claims storage in double.
Default (38,0).
* Sybase: :precision [1..38], :scale [0..38].
Default (38,0).
* SqlServer?: :precision [1..38], :scale [0..38].
NUMERIC is 19, and DECIMAL is 38.
Default (38,0). WARNING Max :precision/:scale for
* FrontBase?: :precision [1..38], :scale [0..38].
storage rules, decimal being better.
Default (9,0). Internal types NUMERIC and DECIMAL have different
* Firebird: :precision [1..18], :scale [0..18].
Default unknown.
* DB2: :precision [1..63], :scale [0..62].
Default is (38,0).
* Oracle: :precision [1..38], :scale [-84..127].
but the maximum supported :precision is 16. No default.
* SQLite3: No restrictions on :precision and :scale,
Internal storage as strings. No default.
* SQLite2: Any :precision and :scale may be used.
:scale [0..infinity]. No default.
* PostgreSQL: :precision [1..infinity],
Default is (10,0).
* MySQL: :precision [1..63], :scale [0..30].
:precision.
:precision, and makes no comments about the requirements of
* The SQL standard says the default scale should be 0, :scale <=
:decimal columns:
Please be aware of different RDBMS implementations behavior with

range from -999.99 to 999.99.
and a scale of 2. A decimal with a precision of 5 and a scale of 2 can
the decimal point. For example, the number 123.45 has a precision of 5
while the scale is the number of digits that can be stored following
For clarity's sake: the precision is the number of significant digits,

Specifies the scale for a :decimal column.
* :scale -
Specifies the precision for a :decimal column.
* :precision -
have been named :null_allowed.
Allows or disallows +NULL+ values in the column. This option could
* :null -
The column's default value. Use nil for NULL.
* :default -
Requests a maximum column length. This is number of characters for :string and :text columns and number of bytes for :binary and :integer columns.
* :limit -
Available options are (none of these exists by default):

agnostic and should usually be avoided.
database (for example, "polygon" in MySQL), but this will not be database
You may use a type not in this list as long as it is supported by your

:date, :binary, :boolean.
:datetime, :timestamp, :time,
:integer, :float, :decimal,
:primary_key, :string, :text,
which is one of the following:
The +type+ parameter is normally one of the migrations native types,
Instantiates a new column for the table.
def column(name, type, options = {})
  column = self[name] || ColumnDefinition.new(@base, name, type)
  if options[:limit]
    column.limit = options[:limit]
  elsif native[type.to_sym].is_a?(Hash)
    column.limit = native[type.to_sym][:limit]
  end
  column.precision = options[:precision]
  column.scale = options[:scale]
  column.default = options[:default]
  column.null = options[:null]
  @columns << column unless @columns.include? column
  self
end

def initialize(base)

def initialize(base)
  @columns = []
  @base = base
end

def method_missing(symbol, *args)

Handles non supported datatypes - e.g. XML
def method_missing(symbol, *args)
  if symbol.to_s == 'xml'
    xml_column_fallback(args)
  end
end

def native

def native
  @base.native_database_types
end

def primary_key(name)

Can be called multiple times, but this is probably not a good idea.
Appends a primary key definition to the table definition.
def primary_key(name)
  column(name, :primary_key)
end

def references(*args)

def references(*args)
  options = args.extract_options!
  polymorphic = options.delete(:polymorphic)
  args.each do |col|
    column("#{col}_id", :integer, options)
    column("#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) unless polymorphic.nil?
  end
end

def timestamps(*args)

:updated_at to the table.
Appends :datetime columns :created_at and
def timestamps(*args)
  options = args.extract_options!
  column(:created_at, :datetime, options)
  column(:updated_at, :datetime, options)
end

def to_sql

to generate the final SQL to create the table.
concatenated together. This string can then be prepended and appended to
Returns a String whose contents are the column definitions
def to_sql
  @columns.map(&:to_sql) * ', '
end

def xml(*args)

def xml(*args)
  options = args.extract_options!
  column(args[0], 'xml', options)
end

def xml_column_fallback(*args)

def xml_column_fallback(*args)
  case @base.adapter_name.downcase
    when 'sqlite', 'mysql'
      options = args.extract_options!
      column(args[0], :text, options)
    end
  end