Rails, Rake, and Databases

| Comments

What happens when using rake database commands in Rails and when should you use them? Let’s take a look at how we can use these commands while developing an application.

This post was inspired by questions I received at ScrappyAcademy. If you like what you read, ask me about how you can get involved.

Creating the Database

$ rake db:create

Your sending a message to your computer that you would like it to create a database for you. For now, you can thing of a database as a container for many different tables which will hold data.

When Should the Database be Created?

When you first create a Rails project or after rake db:drop is ran.

When a Rails application is first created, it does not yet have a database. In order for a Rails application to start, it will require a database to connect to. It is up to us to choose configurations in config/database.yml and tell Rails to create the database.

Creating Tables

$ rake db:migrate

In Rails, we use what are called migration scripts to setup the tables in the database. When the migration command is ran, it will look in db/migrate/ for any ruby files and execute them starting with the oldest. Rails knows which file is the oldest by looking at the timestamp at the beginning of the migration filename. For example, 20110514200813_create_retailers.rb was generated on May 14th, 2011 at 20:08:13 UTC.

When Should Tables Be Created?

After new migration scripts are added or rake db:create.

When we use commands like rails generate scaffold, rails generate model, or rails generate migration, a migration script is created in db/migrations/. The content of the script contains instructions for Rails on what tables to create and how to build them.

Sometimes when developing an application, we want to have a clean slate by destroying and recreating the database. This is another time you’ll want to run database migrations. When the database is deleted, Rails won’t re-create the tables for us unless we tell it to do so.

Setting up Seed Data

$ rake db:seed

Often, we have default data that we want to have in our application that is boring to manually enter each time. The seeds command exists to automate this process. In the seed file, db/seeds.rb you may find admin users, default blog categories, and etc.

When Should I Tell Rails to Add Seed Data?

After new seed data is added to db/seed.rb or rake db:create

Let’s take a look at some example data in db/seeds.rb:

1
2
3
4
Administrator.create(:email => "admin@example.com",
                :name => "Admin"
                :password => "password",
                :password_confirmation => "password")

Whenever data like the above example is added, we’ll want to tell Rails to seed the database. Again, unless Rails is explicitly told to do so, the data will never be added to the database.

Dropping the Database

$ rake db:drop

Sometimes, we want to delete all of the data and tables so that we can start from fresh, that is what this command automates. This will delete the entire database, which holds the tables. Consequently, any data that was in the tables will also be deleted. If you want to keep the data you have, be sure to back the data up before running this command.

When Should I Destroy a Database?

When you want a clean slate or are experience database bugs.

When developing, you will sometimes run into situations where your application and database schema no longer are a perfect match or there is bad data in the development database that is causing errors. When this happens we could manually fix the problem; however, since Rails makes it so easy to rebuild the database you will often find it is easier to start over with a clean slate. Dropping the database will delete the container that holds your tables and data removing any schema conflicts or bad data. At this point, you’ll want to start the process over again by re-creating the database, running migrations, and adding the seed data.

Rolling Back a Migration

$ rake db:rollback

This is the, “I changed my mind” or “Oops, that isn’t what I wanted” command. When this command is run, it will look at the last migration created and undo it.

When Should I Rollback a Migration?

This is great for situations where the schema of the table is still being figured out. Let’s say that you created a new migration with a field as a string, ran the migration, and then decided to make it an integer instead. So you edit the migration you just created, run the migrations, and nothing happens. Why isn’t Rails following your instructions?

When migrations are run, Rails will only run migrations that were created after the last migration it ran. It keeps track of the last migration ran in db/schema.rb. Let’s take a look at the schema file from the above CreateRetailers migration script.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
ActiveRecord::Schema.define(:version => 20110514200813) do
  create_table "retailers", :force => true do |t|
    t.string   "name"
    t.decimal  "lat"
    t.decimal  "lon"
    t.string   "street"
    t.string   "city"
    t.string   "state"
    t.string   "zip"
    t.string   "zip_plus_four"
    t.datetime "created_at"
    t.datetime "updated_at"
  end
end

In line #1, we see :version => 20110514200813. Look familiar? It is the same time stamp from the file name, 20110514200813_create_retailers.rb. Every time a migration is ran, Rails updates the version number to the timestamp from the migration’s filename.

Pulling it all together, running the rollback command tells Rails to do two things, 1) undo the changes I just made to the database and 2) update the version number in the schema file to the previous migrations time stamp. This way, we can edit the migration, run the migrations command, and Rails will pick the change and apply it the the database.

How Do I Use All These Commands Together?

While developing an application, you will find that your run series of commands in sequence often. Here is an order of commands that I use everyday:

1
2
3
4
5
$ rake db:drop
$ rake db:create
$ rake db:migrate
$ rake db:seed
$ rake db:sample

This will give a clean slate, create the database, setup tables, create sample data, and create any seed data.

Wait! You added a new command!

That’s right, for my Rails applications I use to different files for adding data to the database. The sample data is only for the development environment, I don’t ever want to see this sample data showing up in production. The seed data, is for both development and production environments.

You can create your own commands to do to special things to! Here’s an example of my sample of my sample command.

1
2
3
4
5
6
7
8
namespace :db do

  desc "creates sample data"
  task :sample => :environment do
    load File.join(Rails.root, "db", "samples.rb")
  end

end

To learn more about creating your own commands for the database, or any other task, the Rake Readme has great examples, links to presentations, and tutorials.

Have more questions? Grab a time to chat with me and bring your questions!

FAQ

Which Databases will these commands work for?

All of these commands will work on SQL databases such as Sqlite, Postgres, MySql, and etc. Most of these commands will not work with NoSql style databses such as MongoDB. Particually, when working with MongoDB the concept of migrations doesn’t exist formally at this time.

Which version of Rails are you using?

The instructions here are aimed at Rails 3.2.x. In Rails 4, these commands are modified and new ones are added. The general concepts from this guide still apply. To see the changes, here is a link to the source as of 10/27/2013.

Thank You’s

Thanks to the following people for their feedback:

Comments