Class: Cybertrain::Migration::Base

Inherits:
Object
  • Object
show all
Defined in:
cybertrain/migration.rb

Overview

The superclass of every migration in db/migrate/. A file is named <version>_<name>.rb (20260925174942_create_articles.rb) and holds the class <Name> (CreateArticles); the version is the file’s prefix. cybertrain generate scaffold writes one, and cybertrain db migrate applies the pending ones (db rollback [N] reverts), each in a transaction, then rewrites db/schema.rb from the database. Never edit db/schema.rb by hand.

Write change when every operation is reversible (create_table, add_column, add_index, rename_column); otherwise write up and down. SQLite cannot add a foreign key to an existing table, so declare references in create_table or with #add_reference. Not available: rename_table, change_column, change_column_default, change_column_null, create_join_table.

Examples:

class CreateComments < Cybertrain::Migration::Base
  def change
    create_table "comments" do |t|
      t.string "commenter"
      t.text "body"
      t.references :article
      t.timestamps
    end
  end
end

up and down

class RemoveSubtitleFromArticles < Cybertrain::Migration::Base
  def up
    remove_column "articles", "subtitle"
  end

  def down
    add_column "articles", "subtitle", :string
  end
end

Instance Method Summary collapse

Instance Method Details

#add_column(table, name, type, null: true, default: nil, limit: 0) ⇒ nil

Adds a column. Reversible. SQLite adds a NOT NULL column to an existing table only with a non-NULL default:.

Examples:

add_column "articles", "published", :boolean, null: false, default: "false"

Parameters:

  • table (String, Symbol)
  • name (String, Symbol)
  • type (Symbol) —

    :string, :text, :integer, :float, :boolean, :datetime or :date

  • null (Boolean) (defaults to: true)
  • default (String, nil) (defaults to: nil) —

    SQL literal text

  • limit (Integer) (defaults to: 0) —

    VARCHAR(n) for a string when positive

Returns:

  • (nil)


231
232
233
234
# File 'cybertrain/migration.rb', line 231

def add_column(table, name, type, null: true, default: nil, limit: 0)
  @operations << Operation.for_add_column(table.to_s, name.to_s, type, null, default, limit)
  nil
end

#add_index(table, columns, unique: false, name: "") ⇒ nil

Adds an index, named index_<table>_on_<col>_and_<col> unless name: is given. Reversible.

Examples:

add_index "articles", ["slug"], unique: true

Parameters:

  • table (String, Symbol)
  • columns (Array<String, Symbol>)
  • unique (Boolean) (defaults to: false)
  • name (String) (defaults to: "")

Returns:

  • (nil)


268
269
270
271
272
# File 'cybertrain/migration.rb', line 268

def add_index(table, columns, unique: false, name: "")
  cols = columns.map { |c| c.to_s }
  @operations << Operation.for_add_index(table.to_s, cols, unique, name.to_s)
  nil
end

#add_reference(table, name, null: false, foreign_key: true) ⇒ nil

Adds <name>_id (an integer, NOT NULL by default), an index on it and, unless foreign_key: false, a foreign key to the plural table. Not reversible. SQLite adds a NOT NULL column to an existing table only with a default, so pass null: true here; in a new table use Schema::TableDef#references instead.

Parameters:

  • table (String, Symbol)
  • name (Symbol, String) —

    the singular (:author)

  • null (Boolean) (defaults to: false)
  • foreign_key (Boolean) (defaults to: true)

Returns:

  • (nil)


296
297
298
299
300
301
302
303
304
# File 'cybertrain/migration.rb', line 296

def add_reference(table, name, null: false, foreign_key: true)
  column_name = "#{name}_id"
  @operations << Operation.for_add_reference(table.to_s, column_name, null)
  if foreign_key
    to_table = Cybertrain::Inflector.pluralize(name.to_s)
    @operations << Operation.for_add_foreign_key(table, to_table, column_name)
  end
  nil
end

#change

This method returns an undefined value.

Override with the migration’s operations; cybertrain db migrate runs them, and db rollback runs their inverses in reverse order.

Subclasses override change (recorded both ways via inverse) or up/down directly when a migration is not mechanically reversible.



153
154
# File 'cybertrain/migration.rb', line 153

def change
end

#create_table(name) {|t| ... }

This method returns an undefined value.

Creates a table with an id primary key and the columns the block declares. Reversible.

Parameters:

  • name (String, Symbol) —

    the plural ("articles")

Yield Parameters:



195
196
197
198
199
200
# File 'cybertrain/migration.rb', line 195

def create_table(name)
  table = Cybertrain::Schema::Table.new(name)
  yield Cybertrain::Schema::TableDef.new(table)
  @operations << Operation.for_create_table(table)
  table
end

#down

This method returns an undefined value.

What db rollback runs: the inverse of change, unless you override it (together with #up).

The default down runs change to record the forward operations, then replaces them with their inverses in reverse order – it must NOT simply re-run change and keep the forward operations, or a rollback would re-apply the migration instead of undoing it. Raises IrreversibleMigration (via inverse) when change recorded an operation with no automatic inverse.



182
183
184
185
186
187
# File 'cybertrain/migration.rb', line 182

def down
  @operations = empty_operations
  change
  @operations = @operations.reverse.map { |op| inverse(op) }
  nil
end

#drop_table(name) ⇒ nil

Drops a table. Not reversible.

Parameters:

  • name (String, Symbol)

Returns:

  • (nil)


213
214
215
216
# File 'cybertrain/migration.rb', line 213

def drop_table(name)
  @operations << Operation.for_drop_table(name.to_s)
  nil
end

#remove_column(table, name) ⇒ nil

Drops a column (ALTER TABLE ... DROP COLUMN). Not reversible. Drop its indexes first.

Parameters:

  • table (String, Symbol)
  • name (String, Symbol)

Returns:

  • (nil)


242
243
244
245
# File 'cybertrain/migration.rb', line 242

def remove_column(table, name)
  @operations << Operation.for_remove_column(table.to_s, name.to_s)
  nil
end

#remove_index(table, columns) ⇒ nil

Drops the index on these columns. Not reversible.

Parameters:

  • table (String, Symbol)
  • columns (Array<String, Symbol>)

Returns:

  • (nil)


279
280
281
282
283
# File 'cybertrain/migration.rb', line 279

def remove_index(table, columns)
  cols = columns.map { |c| c.to_s }
  @operations << Operation.for_remove_index(table.to_s, cols)
  nil
end

#rename_column(table, from, to) ⇒ nil

Renames a column. Reversible.

Parameters:

  • table (String, Symbol)
  • from (String, Symbol)
  • to (String, Symbol)

Returns:

  • (nil)


253
254
255
256
# File 'cybertrain/migration.rb', line 253

def rename_column(table, from, to)
  @operations << Operation.for_rename_column(table.to_s, from.to_s, to.to_s)
  nil
end

#up

This method returns an undefined value.

What db migrate runs: change, unless you override it (together with #down) because change cannot be reversed automatically.

Both up and down reset @operations before running change so calling either one twice (or calling both on the same instance) never duplicates or mixes forward/backward operations.



164
165
166
167
168
# File 'cybertrain/migration.rb', line 164

def up
  @operations = empty_operations
  change
  nil
end