A seemingly common problem for people learning rails is dealing with multiple iterations of their database and migrations.
A common practice when developing and app is to start with a Model.
rails generate model User name:string email:string
Which would give us something like this
invoke active_record create db/migrate/20130424043103_create_users.rb create app/models/user.rb
Inside the migration file are precise instructions used by Rails to tell your chosen database software (sqlite3, postgresql, mysql etc.) how to create a User table.
class CreateUsers < ActiveRecord::Migration def change create_table :users do |t| t.string :name t.string :email t.timestamps end end end
Over time you can end up with a whole heap of migrations that create tables, drop them, add columns, rename columns and add indexes. like such
20130411094324_devise_create_users.rb 20130411101005_add_column_to_users.rb 20130411121002_create_subpoints.rb 20130411121334_create_items.rb 20130411121453_create_standards.rb 20130411131635_change_standards_column.rb 20130411132400_long_fields.rb 20130412124403_subpoint_column_change.rb 20130413084408_rename_subpoints_to_actions.rb 20130415134525_create_comments.rb 20130416104733_drop_column_title_from_comments.rb
This is all pretty standard stuff, but the issue can arise over time that the migrations can get ‘out of sync’ or you delete a migration without rolling back its changes.
When you get to this point it can be really helpful to have a clean out of your migrations and have a new starting point, particularly once your database structure is stable.
So how to do this?
In your db folder is
Open this up in your text editor and what you will see is the definitions for all of your currently executed migrations!
create_table "comments", :force => true do |t| t.text "comment_text" t.integer "user_id" t.datetime "created_at", :null => false t.datetime "updated_at", :null => false end add_index "comments", ["user_id"], :name => "index_comments_on_user_id" create_table "user_comments", :force => true do |t| t.integer "user_id" t.integer "comment_id" t.datetime "created_at", :null => false t.datetime "updated_at", :null => false end add_index "user_comments", ["comment_id"], :name => "index_user_comments_on_comment_id" add_index "user_comments", ["user_id"], :name => "index_user_comments_on_user_id" create_table "users", :force => true do |t| t.string "name" t.string "email" t.datetime "created_at", :null => false t.datetime "updated_at", :null => false end
create a new migration
rails g migration rebase_my_data_structure
Open this up and copy across the table definitions from schema.rb
You can then delete all previous migrations and happily continue on your way.
This is particularly useful if you are pushing to a new deployment and you don’t want to drag along a complex migration strategy that does lots of unnecessary steps.
In development it can cause some conflicts with the schema_migrations table, and if it does just drop it and run rake db:setup