September 17, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Take Rails to the Cloud: Deploying a Rails Application to Heroku

  • January 20, 2010
  • By Mark Watson
  • Send Email »
  • More Articles »

Heroku, a commercial cloud computing platform for deploying Rails and other Rack-based web applications, uses PostgreSQL database services and provides migration tools to quickly move MySQL (or other relational databases) to its platform. Heroku is deployed on Amazon EC2 and uses Amazon Elastic Block Store (EBS) persistent storage volumes.

Heroku is very simple to use and it abstracts developers from most Rails deployment issues. Its use of Amazon AWS infrastructure services also makes Heroku a good choice for deploying web applications that use other Amazon services, because you pay no bandwidth fees inside specific Amazon zones.

This article explains how to use the Heroku deployment platform by walking you through the development and deployment of a simple database-backed Rails application.

These topics are based on my personal use cases for Heroku deployments and experiments. Hopefully, you will find them useful for your own work and deployments.

Developing and Deploying a Rails Application to Heroku

The examples in this article work towards implementing a simple Rails app: Note Taker with Search. The code download contains all the examples, and you should extract them and work along with me through every example.

Handling User Authentication

To keep the code for the examples short and easy to follow, I will use an easy user-authentication account setup that works well for web apps serving only a few users. Assume that every example contains a text file db/accounts.txt that has a line for each authenticated user, for example:

Mark Watson:mark:mypassword873459435
Otis Watson:otis:otispassword4235244


This shortcut will keep the examples short and make it easier for you to understand the Heroku-specific parts.

Creating the First Rails Project

First, you'll create a Rails project using PostgreSQL and a scaffold that you will customize later. Here is the code to install a few gems you will need and then to generate the Rails application files:

gem install pg
gem install postgres
gem install texticle  # to use PostgreSQL's built in index and search functions
rails --database=postgresql note_taker_pg


You probably should modify the generated database.yml file. I like to fetch any passwords as environment variables. (Later, I'll show you how to register environment variables with Heroku so you don't need to embed them in your source or configuration files). My database.yml file looks like this:

development:
  adapter: postgresql
  encoding: unicode
  database: note_taker_development
  username: postgres
  password: "#{ENV['POSTGRESQL_PASSWORD']}"


You do need to set a PostgreSQL password for Heroku, so leave POSTGRESQL_PASSWORD undefined in your environment unless your local development environment has a password set. I do password protect my postgres PostgresSQL user, so I set it on my laptop. Later, when you use remote MongoDB or CouchDB servers, I'll show you how to set up local config variables on Heroku to specify host names, accounts, and passwords for these remote services.

Now, make sure that the generated web app runs:

script/server


Tip: As a Rails developer, you probably should define bash shell aliases for script/server, script/console, etc. I use rs and rc.

What If You Want to Develop Using MySQL?

You can use an existing Rails application developed with MySQL for this example, as well as develop locally on your laptop using MySQL or SQLite. When you perform the heroku db:push operation, the trick is to move a local database to your Heroku application. If you have your database.yml file configured to use a different database than PostgreSQL, the Heroku system will automatically convert your application to use PostgreSQL. (Later, I'll show you how to set up the database after you finish writing and testing the application locally.)

If you use non-standard SQL features from a different database server, Heroku's documentation has some troubleshooting tips. I have moved three MySQL-based web applications to Heroku and have never had problems.

Finishing the Test Web Application

You can now delete the default HTML page and generate the scaffolds you need:

rm public/index.html
script/generate scaffold Note title:string content:string user_id:integer
script/generate scaffold User login:string password:string


This example uses the scaffold for the User class as a login page. Before you set up the routes for this application and customize the controllers and views, let's finish the models using Aaron Patterson's neat texticle ruby gem to integrate PostgreSQL's text indexing and search features into an ActiveRecord model.

You just need to add a few lines to the Note and User model class definitions to specify that (1) you will use PostgreSQL indexing and search on the Note class fields title and content, and that (2) a user has many notes:

class Note < ActiveRecord::Base
  index do  # define which fields will be indexed for text search
    title
    content
  end 
end
class User < ActiveRecord::Base
  has_many :notes # each user can have many notes
end


I need to modify the User class migration file to read in valid accounts from db/accounts.txt:

class CreateUsers < ActiveRecord::Migration
  def self.up
    create_table :users do |t|
      t.string :login
      t.string :password
      t.timestamps
    end
    User.transaction do
      File.new("db/accounts.txt", "r").readlines.each do |line|
        login, passwd = line.strip.split(':')
        User.new(:login => login, :password => passwd).save
      end
    end
  end
 
  def self.down
    drop_table :users
  end
end


Note that you did not have to modify the generated Note class migration file.

If you want to test this Rails application on your PC before pushing it to Heroku, run a rake task to create the database and another to create the tables on your PC:

rake db:create
rake db:migrate


Tip: When I develop on Rails, I almost always keep a Rails console open. Here is a snippet that checks that two rows are added to the table users during the migration:
script/console
>> u = User.find(1)
=> #<User id: 1, login: "mark", password: "mypassword873459435", 
created_at: "2009-11-13 22:17:31", updated_at: "2009-11-13 22:17:31"> >> u.notes << Note.new(:title => "test title", :content => "test content") => [#<Note id: 1, title: "test title", content: "test content", user_id: 1,
created_at: "2009-11-1322:43:26", updated_at: "2009-11-13 22:43:26">]


If you are not experienced with ActiveRecord, then the last statement may be confusing. Just know that you do not need to set the user ID in the new note object, or to save the new note object; ActiveRecord takes care of both of these operations for you. Also, if you ever remove a note from a user object, ActiveRecord will manage removing the appropriate row from the database table notes.

You are done with the database modeling, but you can now modify the generated controllers and views.


Tags: Ruby on Rails, Cloud, Heroku, cloud services, PostgreSQL



Page 1 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel