class ActiveRecord::ConnectionAdapters::TableDefinition

Represents the schema of an SQL table in an abstract way. This class provides methods for manipulating the schema representation.

Inside migration files, the t object in create_table is actually of this type:

class SomeMigration < ActiveRecord::Migration[6.0]
  def up
    create_table :foo do |t|
      puts t.class  # => "ActiveRecord::ConnectionAdapters::TableDefinition"
    end
  end

  def down
    ...
  end
end

Attributes

as[R]
check_constraints[R]
comment[R]
foreign_keys[R]
if_not_exists[R]
indexes[R]
name[R]
options[R]
temporary[R]

Public Class Methods

new( conn, name, temporary: false, if_not_exists: false, options: nil, as: nil, comment: nil, ** ) click to toggle source
# File lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 301
def initialize(
  conn,
  name,
  temporary: false,
  if_not_exists: false,
  options: nil,
  as: nil,
  comment: nil,
  **
)
  @conn = conn
  @columns_hash = {}
  @indexes = []
  @foreign_keys = []
  @primary_keys = nil
  @check_constraints = []
  @temporary = temporary
  @if_not_exists = if_not_exists
  @options = options
  @as = as
  @name = name
  @comment = comment
end

Public Instance Methods

[](name) click to toggle source

Returns a ColumnDefinition for the column with name name.

# File lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 334
def [](name)
  @columns_hash[name.to_s]
end
belongs_to(*args, **options)
Alias for: references
check_constraint(expression, **options) click to toggle source
# File lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 445
def check_constraint(expression, **options)
  check_constraints << [expression, options]
end
column(name, type, index: nil, **options) click to toggle source

Instantiates a new column for the table. See connection.add_column for available options.

Additional options are:

  • :index - Create an index for the column. Can be either true or an options hash.

This method returns self.

Examples

# Assuming +td+ is an instance of TableDefinition
td.column(:granted, :boolean, index: true)

Short-hand examples

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

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

create_table :products do |t|
  t.column :shop_id,     :integer
  t.column :creator_id,  :integer
  t.column :item_number, :string
  t.column :name,        :string, default: "Untitled"
  t.column :value,       :string, default: "Untitled"
  t.column :created_at,  :datetime
  t.column :updated_at,  :datetime
end
add_index :products, :item_number

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

create_table :products do |t|
  t.integer :shop_id, :creator_id
  t.string  :item_number, index: true
  t.string  :name, :value, default: "Untitled"
  t.timestamps null: false
end

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

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

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

Can also be written as follows using references:

create_table :taggings do |t|
  t.references :tag, index: { name: 'index_taggings_on_tag_id' }
  t.references :tagger, polymorphic: true
  t.references :taggable, polymorphic: { default: 'Photo' }, index: false
end
# File lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 405
def column(name, type, index: nil, **options)
  name = name.to_s
  type = type.to_sym if type

  if @columns_hash[name]
    if @columns_hash[name].primary_key?
      raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
    else
      raise ArgumentError, "you can't define an already defined column '#{name}'."
    end
  end

  @columns_hash[name] = new_column_definition(name, type, **options)

  if index
    index_options = index.is_a?(Hash) ? index : {}
    index(name, **index_options)
  end

  self
end
columns() click to toggle source

Returns an array of ColumnDefinition objects for the columns of the table.

# File lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 331
def columns; @columns_hash.values; end
index(column_name, **options) click to toggle source

Adds index options to the indexes hash, keyed by column name This is primarily used to track indexes that need to be created after the table

index(:account_id, name: 'index_projects_on_account_id')
# File lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 437
def index(column_name, **options)
  indexes << [column_name, options]
end
references(*args, **options) click to toggle source

Adds a reference.

t.references(:user)
t.belongs_to(:supplier, foreign_key: true)
t.belongs_to(:supplier, foreign_key: true, type: :integer)

See connection.add_reference for details of the options you can use.

# File lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 471
def references(*args, **options)
  args.each do |ref_name|
    ReferenceDefinition.new(ref_name, **options).add_to(self)
  end
end
Also aliased as: belongs_to
remove_column(name) click to toggle source

remove the column name from the table.

remove_column(:account_id)
# File lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 429
def remove_column(name)
  @columns_hash.delete name.to_s
end
timestamps(**options) click to toggle source

Appends :datetime columns :created_at and :updated_at to the table. See connection.add_timestamps

t.timestamps null: false
# File lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 453
def timestamps(**options)
  options[:null] = false if options[:null].nil?

  if !options.key?(:precision) && @conn.supports_datetime_with_precision?
    options[:precision] = 6
  end

  column(:created_at, :datetime, **options)
  column(:updated_at, :datetime, **options)
end

Private Instance Methods

aliased_types(name, fallback) click to toggle source
# File lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 493
def aliased_types(name, fallback)
  "timestamp" == name ? :datetime : fallback
end
create_column_definition(name, type, options) click to toggle source
# File lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 489
def create_column_definition(name, type, options)
  ColumnDefinition.new(name, type, options)
end
integer_like_primary_key?(type, options) click to toggle source
# File lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 497
def integer_like_primary_key?(type, options)
  options[:primary_key] && [:integer, :bigint].include?(type) && !options.key?(:default)
end
integer_like_primary_key_type(type, options) click to toggle source
# File lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 501
def integer_like_primary_key_type(type, options)
  type
end