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)
def [](name) @columns_hash[name.to_s] end
def column(name, type, options = {})
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 = {})
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:
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 = {})
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)
Appends :datetime columns :created_at and
def timestamps(*args) options = args.extract_options! column(:created_at, :datetime, options) column(:updated_at, :datetime, options) end