Jared starts a new project for his team. He creates a new User model using the generator:
rails g model User email:string name:string password_digest:string
This command creates two important files (among others), which are:
app/models/user.rb
db/migrate/20160101297348_create_users.rb
The model file is what Rails uses as the bridge between our code and the database. If you look inside the app/models/user.rb file you will see a class defined like:
class User < ApplicationRecord
end
Our User class inherits from ApplicationRecord, which is a class that gives us all the methods we learned like "first", "find", "where". This is less important and we could have created this file manually.
The migration file is what is important here. Migration files are what get executed when we call
rails db:migrate
. It runs only migration files that have not been run already, building out the database in chronological order.
Jared runs rails db:migrate
and it creates a users table with three columns, email, name and password_digest.
Then Jared pushes his code up to Github and tells his team to pull.
Bryan and John pull the code down and run the migrations and start working on their features. At this time Jared realizes that name needs to actually be 'first name' and 'last name'. He goes in and EDITS THE MIGRATION FILE from:
create_table :users do |t|
t.string :email
t.string :name
t.string :password_digest
t.timestamps
end
to:
create_table :users do |t|
t.string :email
t.string :first_name
t.string :last_name
t.string :password_digest
t.timestamps
end
He also updates a file in his helper to use the first and last name attributes:
user = User.find(params[:id])
puts "Greetings, #{user.name}"
to:
user = User.find(params[:id])
puts "Greetings, #{user.first_name}"
Note though that the migration file name remains the same. Jared rolls back his own migrations and reruns them, getting his new database table set up with the new columns. He then pushes the code to GitHub.
Meanwhile John has already added a Posts table and a Comments table to his branch. Bryan has merged some of this into his own branch as well. They've both run migrations several times. What will happen when they attempt to use Jared's code?
Instead of editing a migration file, Jared should have created a new migration file that alters the existing table. Since the model already exists, we can just use the generator to create a migration file. The naming for a migration is arbitrary but should be descriptive. It would look something like this:
rails g migration AddFirstNameToUsers first_name:string
which creates a new migration file:
class AddFirstNameToUsers < ActiveRecord::Migration[5.0]
def change
add_column :users, :first_name, :string
end
end
And then another to rename the coumn name to last_name:
rails g migration ChangeNameToLastname
Which generates:
class ChangeNameToLastname < ActiveRecord::Migration[5.0]
def change
end
end
Note this is an empty migration file. Changing is too advanced to specify using the generator. We have to write it manually. See Active Record Migrations Documentation for more information.
We add this line:
class ChangeNameToLastname < ActiveRecord::Migration[5.0]
def change
rename_column :users, :name, :last_name
end
end
Remember this is just a method call like rename_coumn(:table, :old_column_name, :new_column_name)
The key point here is that now when a user runs migrations, they will playback files in chronological order. It will build the table with the name column and then update it to use first and last name. This ensures that everyone has the exact same database!
This also ensures the ghost of Bryan Mytko doesn't haunt your laptop because you edited migrations.