As a beginner to Rails, I was impressed by the power of Rails migration generator. Rails generators enable developers to utilize the Command Line Use interface to create an enormous amount of code in a streamlined manner.
If you run "rails g" at the command prompt, you get the following output:
General options:
-h, [--help] # Print generator's options and usage
-p, [--pretend] # Run but do not make any changes
-f, [--force] # Overwrite files that already exist
-s, [--skip] # Skip files that already exist
-q, [--quiet] # Suppress status output
Please choose a generator below.
Rails:
application_record
benchmark
channel
controller
generator
integration_test
job
mailbox
mailer
migration
model
resource
scaffold
scaffold_controller
serializer
system_test
task
We will be discussing the migration generator. The migration generator allows the developer to define a new table or make a change to an existing table. For example, let's create a teams table with columns name and city. We can run the following generator at the CLI prompt.
rails g migration CreateTeams name:string city:string
The output from running this generator is the following.
(base) craigjford@Craigs-iMac test-app % rails g migration CreateTeams name:string city:string
invoke active_record
create db/migrate/20230121200306_create_teams.rb
Rails will generate the following migration.
class CreateTeams < ActiveRecord::Migration[7.0]
def change
create_table :teams do |t|
t.string :name
t.string :city
t.timestamps
end
end
end
We will now run "Rails db:migrate" from the CLI and recive the following input.
== 20230121200306 CreateTeams: migrating ======================================
-- create_table(:teams)
-> 0.0014s
== 20230121200306 CreateTeams: migrated (0.0014s) =============================
Since this is our first table, a new schema file will be created after we run the "Rails db:migrate" command.
ActiveRecord::Schema[7.0].define(version: 2023_01_21_200306) do
create_table "teams", force: :cascade do |t|
t.string "name"
t.string "city"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
Suppose we forgot to include a type field to the table. We
can simply create an additional migration as follows.
rails g migration AddTypeToTeams
This will create another migration file as seen below.
class AddTypeToTeams < ActiveRecord::Migration[7.0]
def change
add_column :teams, :type, :string #we need to add this
end
end
If we run db:migrate once more, the schema will look as follows.
ActiveRecord::Schema[7.0].define(version: 2023_01_21_203133) do
create_table "teams", force: :cascade do |t|
t.string "name"
t.string "city"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "type"
end
end
Suppose we now want to add a Players table and that we want the relationships that a teams has many players and a players belongs to a team. We can utilize the migration generator in the following way.
rails g migration CreatePlayers team:belongs_to player_team:string
Rails will provide the following output.
(base) craigjford@Craigs-iMac test-app % rails g migration CreatePlayers team:belongs_to player_team:string
invoke active_record
create db/migrate/20230121205723_create_players.rb
Rails migration generator creates the following output.
(base) craigjford@Craigs-iMac test-app % rails g migration CreatePlayers team:belongs_to player_team:string
invoke active_record
create db/migrate/20230121205723_create_players.rb
The migration generator creates the following migration file.
class CreatePlayers < ActiveRecord::Migration[7.0]
def change
create_table :players do |t|
t.belongs_to :team, null: false, foreign_key: true
t.string :player_team
t.timestamps
end
end
end
Running "rails db:migrate" now updates the schema to look like the following.
ActiveRecord::Schema[7.0].define(version: 2023_01_21_205723) do
create_table "players", force: :cascade do |t|
t.integer "team_id", null: false
t.string "player_team"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["team_id"], name: "index_players_on_team_id"
end
create_table "teams", force: :cascade do |t|
t.string "name"
t.string "city"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "type"
end
add_foreign_key "players", "teams"
end
As you can see, in a short period of time we have created three migration files. We have run the db:migrates and have created a working schema file that has a one-to-many relationship.
This post really just skims the surface of what you can do with the rails migration generator. If we run the following command "rails g migration --help", we can see all the other options available with rails g migration.
Usage:
rails generate migration NAME [field[:type][:index] field[:type][:index]] [options]
Options:
[--skip-namespace], [--no-skip-namespace] # Skip namespace (affects only isolated engines)
[--skip-collision-check], [--no-skip-collision-check] # Skip collision check
-o, --orm=NAME # ORM to be invoked
# Default: active_record
ActiveRecord options:
[--timestamps], [--no-timestamps] # Indicates when to generate timestamps
# Default: true
[--primary-key-type=PRIMARY_KEY_TYPE] # The type for primary key
--db, [--database=DATABASE] # The database for your migration. By default, the current environment's primary database is used.
Runtime options:
-f, [--force] # Overwrite files that already exist
-p, [--pretend], [--no-pretend] # Run but do not make any changes
-q, [--quiet], [--no-quiet] # Suppress status output
-s, [--skip], [--no-skip] # Skip files that already exist
Description:
Generates a new database migration. Pass the migration name, either
CamelCased or under_scored, and an optional list of attribute pairs as arguments.
A migration class is generated in db/migrate prefixed by a timestamp of the current date and time.
You can name your migration in either of these formats to generate add/remove
column lines from supplied attributes: AddColumnsToTable or RemoveColumnsFromTable
Example:
`bin/rails generate migration AddSslFlag`
If the current date is May 14, 2008 and the current time 09:09:12, this creates the AddSslFlag migration
db/migrate/20080514090912_add_ssl_flag.rb
`bin/rails generate migration AddTitleBodyToPost title:string body:text published:boolean`
This will create the AddTitleBodyToPost in db/migrate/20080514090912_add_title_body_to_post.rb with this in the Change migration:
add_column :posts, :title, :string
add_column :posts, :body, :text
add_column :posts, :published, :boolean
Migration names containing JoinTable will generate join tables for use with
has_and_belongs_to_many associations.
Example:
`bin/rails g migration CreateMediaJoinTable artists musics:uniq`
will create the migration
create_join_table :artists, :musics do |t|
# t.index [:artist_id, :music_id]
t.index [:music_id, :artist_id], unique: true
end
Happy hacking!
Top comments (0)