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?

Easy!

In your db folder is

schema.rb

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

 

 

 

 

 

 

 

Leave a reply

required


nine + = 13

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>