424

I have a Users model which needs an :email column (I forgot to add that column during the initial scaffold).

I opened the migration file and added t.string :email, did rake db:migrate, and got a NoMethodError. Then I added the line

add_column :users, :email, :string

again rake db:migrate, again NoMethodError. Am I missing a step here?

Here's the migration file.

class CreateUsers < ActiveRecord::Migration  
  def self.up  
    add_column :users, :email, :string  
    create_table :users do |t|  
      t.string :username  
      t.string :email  
      t.string :crypted_password  
      t.string :password_salt  
      t.string :persistence_token  

      t.timestamps  
    end  
  end  

  def self.down  
    drop_table :users  
  end  
end
ggorlen
  • 44,755
  • 7
  • 76
  • 106
John
  • 5,835
  • 8
  • 28
  • 36

11 Answers11

701

If you have already run your original migration (before editing it), then you need to generate a new migration (rails generate migration add_email_to_users email:string will do the trick). It will create a migration file containing line: add_column :users, email, string Then do a rake db:migrate and it'll run the new migration, creating the new column.

If you have not yet run the original migration you can just edit it, like you're trying to do. Your migration code is almost perfect: you just need to remove the add_column line completely (that code is trying to add a column to a table, before the table has been created, and your table creation code has already been updated to include a t.string :email anyway).

ARK
  • 772
  • 7
  • 21
Dylan Markow
  • 123,080
  • 26
  • 284
  • 201
193

Use this command on the terminal:

rails generate migration add_fieldname_to_tablename fieldname:string

and

rake db:migrate

to run this migration

michaelrbock
  • 1,160
  • 1
  • 11
  • 20
vinodh
  • 2,114
  • 1
  • 12
  • 17
88

Sometimes rails generate migration add_email_to_users email:string produces a migration like this

class AddEmailToUsers < ActiveRecord::Migration[5.0]
  def change
  end
end

In that case you have to manually an add_column to change:

class AddEmailToUsers < ActiveRecord::Migration[5.0]
  def change
    add_column :users, :email, :string
  end
end

And then run rake db:migrate

Jon Schneider
  • 25,758
  • 23
  • 142
  • 170
Apurv Agarwal
  • 3,008
  • 18
  • 19
  • 1) Should `rails generate migration add_email_to_users email:string` this be run after `bundle exec rails c` or just within the terminal ? 2) Where is the generated file placed once we execute the query? – sofs1 Nov 22 '19 at 00:18
  • @sofs1 just in the terminal. The new file is created in `/db/migrate/` – stevec Sep 18 '20 at 01:00
29

You can also do

rake db:rollback

if you have not added any data to the tables.Then edit the migration file by adding the email column to it and then call

rake db:migrate

This will work if you have rails 3.1 onwards installed in your system.

Much simpler way of doing it is change let the change in migration file be as it is. use

$rake db:migrate:redo

This will roll back the last migration and migrate it again.

Soviut
  • 88,194
  • 49
  • 192
  • 260
Ninz
  • 349
  • 5
  • 13
25

To add a column I just had to follow these steps :

  1. rails generate migration add_fieldname_to_tablename fieldname:string

    Alternative

    rails generate migration addFieldnameToTablename

    Once the migration is generated, then edit the migration and define all the attributes you want that column added to have.

    Note: Table names in Rails are always plural (to match DB conventions). Example using one of the steps mentioned previously-

    rails generate migration addEmailToUsers

  2. rake db:migrate

Or

  1. You can change the schema in from db/schema.rb, Add the columns you want in the SQL query.
  2. Run this command: rake db:schema:load

    Warning/Note

    Bear in mind that, running rake db:schema:load automatically wipes all data in your tables.

Afolabi Olaoluwa
  • 1,898
  • 3
  • 16
  • 37
Pratik Naik
  • 410
  • 4
  • 13
  • I did this, but it did not redo the "scaffolding" and add the new column. How can I do that "automagically"? – John Wooten Jul 27 '16 at 13:34
  • @John Wooten, you might wanna delete the Scaffold and go through it again. Drop corresponding migrations too. – Afolabi Olaoluwa Aug 10 '16 at 15:31
  • to add a note: changing the schema without changing the migration may create issues with other developers maintaining the app. – BenKoshy Feb 08 '18 at 23:23
9

You can also add column to a specific position using before column or after column like:

rails generate migration add_dob_to_customer dob:date

The migration file will generate the following code except after: :email. you need to add after: :email or before: :email

class AddDobToCustomer < ActiveRecord::Migration[5.2]
  def change
    add_column :customers, :dob, :date, after: :email
  end
end
Khabir
  • 5,370
  • 1
  • 21
  • 33
  • 1
    To save anyone wasting time, I (intuitively) tried before: :somecol and that doesn't work (it will still add the column, but will add it to the far right of the table) – stevec Sep 26 '20 at 11:50
  • Doesn't work in PostgreSQL. See: https://dba.stackexchange.com/q/3276 – mechnicov Mar 18 '21 at 23:51
4

You also can use special change_table method in the migration for adding new columns:

change_table(:users) do |t|
  t.column :email, :string
end
ruslanimos
  • 41
  • 4
3

When I've done this, rather than fiddling the original migration, I create a new one with just the add column in the up section and a drop column in the down section.

You can change the original and rerun it if you migrate down between, but in this case I think that's made a migration that won't work properly.

As currently posted, you're adding the column and then creating the table.

If you change the order it might work. Or, as you're modifying an existing migration, just add it to the create table instead of doing a separate add column.

Don Roby
  • 40,677
  • 6
  • 91
  • 113
1

You can also do this .. rails g migration add_column_to_users email:string

then rake db:migrate also add :email attribute in your user controller ;

for more detail check out http://guides.rubyonrails.org/active_record_migrations.html

aaquib
  • 25
  • 6
1

You can also force to table columns in table using force: true, if you table is already exist.

example:

ActiveRecord::Schema.define(version: 20080906171750) do
  create_table "authors", force: true do |t|
    t.string   "name"
    t.datetime "created_at"
    t.datetime "updated_at"
  end
end
Aravin
  • 6,605
  • 5
  • 42
  • 58
0

You could rollback the last migration by

rake db:rollback STEP=1

or rollback this specific migration by

rake db:migrate:down VERSION=<YYYYMMDDHHMMSS>

and edit the file, then run rake db:mirgate again.

Fangxing
  • 5,716
  • 2
  • 49
  • 53