Fran b
Fran b

Reputation: 3036

Guidelines about using of migrate on Rails

I have already read the documentation of "migrate" on Rails 3 (Rails 3.0 Relese Notes Migrate) but I have some doubts.

e.g. I created two class:

rails generate scaffold User name:string age:integer height:float

rails generate scaffold Hat type:string width:float height:float

This create models, controllers, ... User and Hat and its migrate class: xxx_create_users.rb and xxx_create_hats.rb

Ok, now we guess we want modify User class and we delete height attribute, and we add the relationships between Users and Hats:

User

class User < ActiveRecord::Base
  attr_accessible :name, :age

  has_many :hats
end

Hat

class Hat < ActiveRecord::Base
  attr_accessible :type, :width, height

  belongs_to :user
end

Options that I guess:

  1. I remove all files xxx_create_xxx.rb and then I will create again with: rails generate migration CreateUser (and the same for Hat)

  2. I create a new migration file: rails generate migration MyNewMigration where I codify by hand all changes.

Is there another way to automate changes in my classes for passed it to the database? What is the correct way to proceed?

Upvotes: 2

Views: 383

Answers (3)

Dennis Hackethal
Dennis Hackethal

Reputation: 14295

The idea of migrations is that you have a stringent storyline where you can start at any point, forward and backwards. This means that it should not ever be necessary to delete a migration.

Instead, you create a new migration that will change, remove or add database fields.

In your example, you would leave the old migration where it is and then create a new migration like so:

rails g migration change_user_fields

And inside def up you write

remove_column :table_name, :column_name
change_column :table_name, :column_name, :data_type

Add a def down - this will be run whenever the migration is reversed by rake db:rollback. Inside def down put:

add_column :table_name, :column_name # add the field that you removed (s.a.)
change_column :table_name, :column_name, :data_type # change back to old data type

Rails 3 gives you a nice shortcut for adding and removing fields from a table by doing:

rails g migration add_something_to_users name:string

which will automatically create a migration that adds a field called name with a data type of string to the users table. Or

rails g migration remove_something_from_users name

which will automatically create a migration to remove the name field from the users table. These shortcuts and the created migration files do not need a def down - rails will automatically be smart enough to figure that out when reversed.

In both cases, you can replace the word "something" with whatever you like.

However, I know of no way to use a shortcut to change data types, so you need to go in the migration file and do that manually.

Eventually, just run rake db:migrate and you'll be all set!

Upvotes: 3

Jakob W
Jakob W

Reputation: 3377

The answer to your question should be alternative 2. But you don't have to do it all by hand if you just want to add or remove attributes: http://guides.rubyonrails.org/migrations.html#creating-a-standalone-migration

Upvotes: 0

MurifoX
MurifoX

Reputation: 15109

Scaffold only automate a fixed command, so if you create a model and its attributes with scaffold, your migration will only contain the fields you specify on the command line. There is no way to keep track of changes automatically.
If you add/remove/change something on your database, you have to manually set it. Migrations are useful because you can keep track of these changes on time.
So i recommend you to never delete a migration. In this particular case you described, you just have to create another one to reflect the new change on your database, keeping a total of 3 migrations, instead of deleting and creating another.

Upvotes: 1

Related Questions