class ActiveRecord::ConnectionAdapters::TableDefinition

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

def down
end
end
puts t.class # => “ActiveRecord::ConnectionAdapters::TableDefinition”
create_table :foo do |t|
def up
class SomeMigration < ActiveRecord::Migration
is actually of this type:
Inside migration files, the t object in create_table
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_hash[name.to_s]
end

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

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

Can also be written as follows using references:

add_index :taggings, [:tagger_id, :tagger_type]
add_index :taggings, :tag_id, name: 'index_taggings_on_tag_id'
end
t.string :taggable_type, default: 'Photo'
t.string :tagger_type
t.integer :tag_id, :tagger_id, :taggable_id
create_table :taggings do |t|

will also create an index, similar to calling add_index. So what can be written like this:
options, these will be used when creating the _type column. The :index option
column if the :polymorphic option is supplied. If :polymorphic is a hash of
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 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 -
:text columns and number of bytes for :binary and :integer columns.
Requests a maximum column length. This is number of characters for :string and
* :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 = {})
  name = name.to_s
  type = type.to_sym
  if primary_key_column_name == name
    raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
  end
  @columns_hash[name] = new_column_definition(name, type, options)
  self
end

def columns; @columns_hash.values; end

def columns; @columns_hash.values; end

def create_column_definition(name, type)

def create_column_definition(name, type)
  ColumnDefinition.new name, type
end

def index(column_name, options = {})

index(:account_id, name: 'index_projects_on_account_id')

This is primarily used to track indexes that need to be created after the table
Adds index options to the indexes hash, keyed by column name
def index(column_name, options = {})
  indexes[column_name] = options
end

def initialize(types, name, temporary, options)

def initialize(types, name, temporary, options)
  @columns_hash = {}
  @indexes = {}
  @native = types
  @temporary = temporary
  @options = options
  @name = name
end

def native

def native
  @native
end

def new_column_definition(name, type, options) # :nodoc:

:nodoc:
def new_column_definition(name, type, options) # :nodoc:
  column = create_column_definition name, type
  limit = options.fetch(:limit) do
    native[type][:limit] if native[type].is_a?(Hash)
  end
  column.limit       = limit
  column.array       = options[:array] if column.respond_to?(:array)
  column.precision   = options[:precision]
  column.scale       = options[:scale]
  column.default     = options[:default]
  column.null        = options[:null]
  column.first       = options[:first]
  column.after       = options[:after]
  column.primary_key = type == :primary_key || options[:primary_key]
  column
end

def primary_key(name, type = :primary_key, options = {})

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, type = :primary_key, options = {})
  column(name, type, options.merge(:primary_key => true))
end

def primary_key_column_name

def primary_key_column_name
  primary_key_column = columns.detect { |c| c.primary_key? }
  primary_key_column && primary_key_column.name
end

def references(*args)

def references(*args)
  options = args.extract_options!
  polymorphic = options.delete(:polymorphic)
  index_options = options.delete(:index)
  args.each do |col|
    column("#{col}_id", :integer, options)
    column("#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) if polymorphic
    index(polymorphic ? %w(id type).map { |t| "#{col}_#{t}" } : "#{col}_id", index_options.is_a?(Hash) ? index_options : {}) if index_options
  end
end

def remove_column(name)

def remove_column(name)
  @columns_hash.delete name.to_s
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