Rails Tutorial Part 2: Setting Up a Server on Heroku for Free!

Continuing from my previous post, in part two of this Rails Tutorial I am going to continue to add to my nascent project. The theme of the project is getting set up on heroku with lots of cool addons … for FREE!.

In part two we will be adding, as promised:

  • Papertrail: an awesome log management service (free)
  • New Relic: Site monitoring (free)
  • PG Backups: postgres backup (free)

Like most heroku add-ons, adding Papertrail was a piece of cake. Just go to the Papertrail add-on page and choose the “Choklad” (i.e. FREE) option. Done.

I add New Relic by simply going to https://addons.heroku.com/ and selecting the either the ‘Stark’ or ‘Wayne’ free version. (I’m not sure which one will better suit my needs, but I’ll go with the one that offers more features for now. I can always switch to another configuration later.)

When I went to verify that everything was connecting, however, I only received a generic message saying “Welcome, ! Thanks for taking advantage of our partnership with heroku.” For some reason it’s not clicking.

Turns out my server was not running correctly. Fortunately, Papertrail helped me track down the source of the issue: My app was not connecting to the Postgres DB successfully. The error message was “FATAL: password authentication failed for user “zapetulgfrdywm” (PG::Error).”

StackOverflow to the rescue, of course. I had to “promote” my heroku DB – I guess it was trying to use the credentials from my local DB. Once I did that the errors went away and my server was up and running successfully.

At this point I went back to New Relic to see if it was starting to show any monitoring information. It wasn’t. Solution: Fortunately it was simple. I just restarted heroku

heroku restart

Not much to show so far, of course, but it looks like it’s running. Yay!

Finally, I’d like to add PG Backups to make regular, automatic (and FREE) backups of my DB. To add it, just go to the PG Backups page and choose one of the three options: “Auto – One Month Retention,” “Auto – One Week Retention,” or “Plus.” I must admit I don’t really understand the differences between the options. The “Plus” option seems geared toward people who want to only do manual backups, but the two “Auto” options seem pretty similar. Maybe the One Month Retention option seems superior. That’s the one I chose anyway. Maybe I’ll discover something preferable about the One Week Retention option later.

Looks like I’m ready to start coding! More specifically, I’m ready for part 3: Getting users authenticated so they can eventually create content for my site.

Rails Tutorial: Setting Up a Server on Heroku for Free!

In this Rails tutorial I am going to set up dev, stage, and production environments. Dev will be on my local machine and I’ll use heroku for stage and production. I’m going to use Unicorn to provide a performance boost and I’ll use postgres as my DB because that’s what heroku will allow me to use.

Why use Unicorn, you may ask. I’m no expert on servers and performance, so I’ll let this quote speak for itself (from “More concurrency on a single Heroku dyno with the new Celadon Cedar stack” by Michael van Rooijen. Read it!).

In any case, what’s important to understand for now is the fact that there’s a master process which loads in your application’s environment, and forks off child processes to serve your application.

The first step to set up my site is to create my local (dev) environment with the basic rails new [app_name] from my command line. [Note that you may want to run rails new [app_name] -d postgresql instead. I haven’t tried it yet but it may save some steps described below.

Next I create my git repository on Bitbucket. The process is terribly simple. Just go to Bitbucket.com, click “Create a repository,” then follow their very clear instructions for adding and committing your source files to your new repo.

After I commit my files, I set up unicorn. I follow the simple instructions in the blog entry “Deploying Rails Applications With Unicorn” and, after running foreman start at the command line, I now have Unicorn running smoothly locally.

Heroku doesn’t like the default db, sqlite, so I followed the instructions in the ASCIICast version of Railscast #342 so I can use postgresql instead. I then edit my ‘database.yml’ file as instructed in the Railscast and StackOverflow thread. When I try to run rake db:create:all, however, I get an error saying I need to run gem install activerecord-postgresql-adapter. So I do. I also change  gem ‘sqlite3’ to  gem ‘pg’ in my Gemfile. Now when I run rake db:create:all, all is good.

Note that in previous attempts to set up my environment, I have run into the same problem as the Railscast commenter “blackpond” – my environment was still using the old version of postgres that cam installed on my mac. Fortunately user “aharte” had the suggestion that worked:

Edit /etc/paths and make sure /usr/local/bin is above /usr/bin in the file. Open a new shell, and you’re good to go!

When I try to push to heroku, however, it complains that I am still using sqlite. I didn’t add my Gemfile to the repo! Simply do a normal git add . followed by git commit -m “[message], then push to heroku with git push staging master and we’re good to go.

Well, not quite. After changing /etc/paths I was getting a “role does not exist” error. This StackOverflow thread recommended that I remove ‘username’ line for my stage and production servers in my database.yml file. It worked!

Now to hook everything up with heroku. I carefully followed the instructions on the Managing Multiple Environments for an App how-to page on heroku.com. This set up my staging and production servers.

Now if I run git push stage master everything processes correctly on the heroku side of things for my stage environment. When things look good on stage, I can just run git push stage production. Woo-hoo!

In the next part of this series, I’m going to add a few add-ons to my heroku set up:

  • Papertrail: an awesome log management service (free)
  • PG Backups: postgres backup (free)
  • New Relic: Site monitoring (free)

Definitely a theme going on here: FREE! If the site gets rolling, hopefully I’ll need to upgrade things, but for now my set up definitely works fine.

Ruby on Rails Cheat Sheet Part 2 – More Tips and Reminders

I am still finding new Ruby and Ruby on Rails tricks (and I keep forgetting them) so I am starting a second Ruby on Rails cheat sheet to help me remember how to accomplish simple tasks.

Check out my first Ruby on Rails cheat sheet if you’re interested. It’s based on the Ruby on Rails Tutorial by Michael Hartl.

Set up a new Heroku app:

heroku apps:create app-name

Push git repo to new Heroku app:

git push heroku master

Reset a postgres DB on Heroku:

heroku pg:reset postgres

View Heroku logs:

heroku logs

Restart Heroku server:

heroku restart

Migrate DB on Heroku server:

heroku run rake db:migrate

Generate a resource without controller actions and without a view

rails g resource resource_name {space-delimited property names}

 

 

Ruby on Rails Tutorial: Creating a Rails Instance from an Existing MySQL DB

In this Ruby on Rails tutorial, I will show how to create a Rails instance from an existing MySQL database.

I have an existing site that used Codeigniter and a MySQL DB, and I want to more or less convert that site into a Ruby on Rails site. I would like to make things as automatic as possible so I don’t have to manually port any of the existing data or create the model properties.

I found this thread on ruby-forum.com that explains the basics of how to migrate an existing MySQL DB so it works with Rails. Let’s follow the steps provided:

1. Write config/database.yml to reference your database.
I’m going to follow the guidelines in the RailsGuides for configuring a MySQL DB. The guidelines say that I should change my config/database.yml file to look something like this:

development:
  adapter: mysql2
  encoding: utf8
  database: blog_development
  pool: 5
  username: root
  password:
  socket: /tmp/mysql.sock

With some small tweaks to match my local environment, I’m ready for step 2:

2. Run “rake db:schema:dump” to generate db/schema.rb.
First stumbling block. I get the following error upon trying “rake db:schema:dump”:
Please install the mysql2 adapter: `gem install activerecord-mysql2-adapter` (mysql2 is not part of the bundle. Add it to Gemfile.)

After following the suggestions I’ve been given (1. gem install activerecord-mysql2-adapter and 2. Adding “gem ‘mysql2′” to my Gemfile) I try “rake db:schema:dump” again.

Second stumbling block. I get this error:
Can’t connect to local MySQL server through socket ‘/tmp/mysql.sock’ (2)

This StackOverflow thread tells me that I need to figure out the correct socket file and specify it in my database.yml file. I run ‘mysqladmin variables | grep socket’ from the command line and find out that my socket file is located at ‘/Applications/XAMPP/xamppfiles/var/mysql/mysql.sock’ because, of course, I’m running XAMPP for my MySQL server.

Success! Well, I think so anyway. At least I didn’t get any error messages this time.

3. Convert schema.rb into db/migrate/001_create_database.rb
My schema.rb file reflects a successful connection to my MySQL DB. It seemingly faithfully describes the tables and fields of my DB. So I create a ‘/db/migrate’ folder, copy my ‘schema.rb’ file into it, rename it ‘001_create_database.rb’ and wrap the schema as suggested by the ruby-forums.com thread:

class CreateDatabase < ActiveRecord::Migration
  def self.up
    # insert schema.rb here
  end

  def self.down
    # drop all the tables if you really need
    # to support migration back to version 0
  end
end

One note about this: The instructions in the ruby-forums.com thread say the first line of the migration file should be:

class CreateMigration < ActiveRecord::Migration

But it didn’t work for me until I changed it to:

class CreateDatabase < ActiveRecord::Migration

(Note the updated class name.) All good now.

So now I think I have what I need to create the DB if I need to.

Now for the cool part. If I create a simple model whose class name matches one of the tables in my DB, I can immediately start accessing the data in the DB. Simple model:

class Tweet < ActiveRecord::Base
  # I have a table called 'tweets' in the DB
end

Now in the Rails console I can type:

> i = Tweet.find(296) # 296 is an ID of an item in the DB

And I get the data related to that record!

One last thing to really show that a connection has actually been made to the old DB. I want to display some records in the browser. There are really only three steps to accomplish this, but I’ll add a fourth step to allow for pagination between all the records.

Step 1: Add routes to set up basic CRUD functions
This is pretty simple, just add the following line to the beginning of the routes.rb file:

resources :tweets   # replace 'tweet' with the name of your model

Now if I go to http://0.0.0.0:3000/tweets I get an error “uninitialized constant TweetsController.” That’s because, well, I haven’t created my Tweets controller.

Step 2: Add a controller and define an index function
In the ‘/app/controllers’ directory, I simply created a file called ‘tweets_controller.rb’ and added the following text (replacing the names of the classes and models as necessary):

class TweetsController < ApplicationController
 def index
    @tweets = Tweet.paginate(page: params[:page], :per_page => 10)
 end
end

This won’t work until we get through step 3.

Step 3: Add the ‘will_paginate’ gem
In the Gemfile, add the following line:

gem 'will_paginate', '3.0.3'

Then run ‘bundle install’

Step 4: Create a view
In the ‘/app/views’ directory I created a ‘tweets’ directory and within that directory I created a file called ‘index.html.erb’. The ‘index’ part of that file name matches the index function of my TweetsController for a reason – this view gets called automatically when the user goes to ‘/tweets/index.html’.

In the same ‘/app/views/tweets/’ directory I create a very simple partial file that will be called whenever an individual tweet needs to be displayed. That file is called “_tweet.html.erb” and the contents look like this:

<li>
  <!-- tweet_text is a field in the tweets table -->
  <%= tweet.tweet_text %> 
</li>

The contents of the ‘/app/views/tweets/index.html.erb’ file I mentioned above look like this:

<%= will_paginate %>
 <ul class="users">  <!-- Knows to repeatedly render the _tweets partial -->  <%= render @tweets %>  </ul> <%= will_paginate %>

And that’s it! I get all my DB records listed, 10 at a time, with pagination links so I can jump around between them. There’s no formatting and a lot more work will go into displaying and organizing the data, but this is a really good start.

I create these rough tutorials as I go, so I fear some of the info may be disjointed or inconsistent. Please let me know if you have any questions or need anything clarified. I’m happy to help.

Ruby on Rails Cheat Sheet – Handy Tips Gleaned from RoR Tutorial Book

Every time I go away from RoR for a while, I forget everything I had learned. In order to get me up to speed more quickly in the future, I am going to create a Ruby on Rails cheat sheet that describes how to accomplish simple tasks with Rails.

These tips all come from the Ruby on Rails Tutorial by Michael Hartl and the section #s below refer to it (http://ruby.railstutorial.org/book).

Create static pages (3.1.2):

Tell generate to use RSpec:

rails generate rspec:install

Generate static pages:

// generates home and help pages
rails generate controller StaticPages home help --no-test-framework

 Undoing generate commands

// Example
rails generate controller FooBars baz quux
rails destroy  controller FooBars baz quux
// Example 2
$ rails generate model Foo bar:string baz:integer
$ rails destroy model Foo
// Rake db:migrate example
rake db:migrate
rake db:rollback

Everything in Ruby (even a string and nil) is an object (4.2.3)

nil.to_s
=> ""
"foobar".empty?
=> false

 Array operations followed by a bang (!) affect the array (4.3.1)

>> a
=> [42, 8, 17]
>> a.sort
=> [8, 17, 42]
>> a
=> [42, 8, 17]
>> a.sort!
=> [8, 17, 42]
>> a
=> [8, 17, 42]

You can think of symbols as basically strings without all the extra baggage (4.3.3)

>> user = { :name => "Michael Hartl", :email => "a@b.com" }
=> {:name=>"Michael Hartl", :email=>"a@b.com"}
>> user[:name]       # Access the value corresponding to :name.
=> "Michael Hartl"

Alternate syntax for using symbols as hash keys (4.3.3):

>> h1 = { :name => "Michael Hartl", :email => "michael@example.com" }
=> {:name=>"Michael Hartl", :email=>"michael@example.com"}
>> h2 = { name: "Michael Hartl", email: "michael@example.com" }
=> {:name=>"Michael Hartl", :email=>"michael@example.com"} 
>> h1 == h2
=> true

Adding Bootstrap and Sass (5.1.2)

  1. Make sure the bootstrap gem is listed in your gemfile
    gem 'bootstrap-sass', '2.0.4'
  2. Create a Sass file (app/assets/stylesheets/custom.css.scss) with the following line
    @import "bootstrap";
  3. That’s it!

Creating and referencing partials (5.1.3)

  1. File name and location:
    app/views/layouts/_partial_name.html.erb
  2. Reference to partial:
    <%= render 'layouts/partial_name' %>

 Asset directories and their purposes (5.2.1)

  • app/assets: assets specific to the present application
  • lib/assets: assets for libraries written by your dev team
  • vendor/assets: assets from third-party vendors

Each has images, javascripts, and stylesheets subdirectories.

Routes to static pages (5.3.2)

The following line redirects /help to the help.html.erb layout in the static_pages directory

match '/help',    to: 'static_pages#help''

It also creates the following two named routes:

about_path => '/about'
about_url  => 'http://localhost:3000/about'

Creating a controller (5.4.1)

# Creates a simple "new" view and empty "new" controller method
# --no-test-framework prevents creation of initial testing spec
rails generate controller Users new --no-test-framework

Creating a model (6.1.1)

rails generate model User name:string email:string

 Annotating model definitions with details from their DB counterparts (6.1.2)

# Add gem to Gemfile (only for development)
gem 'annotate', '2.5.0', group: :development
# Goes through DB tables and comments corresponding model files
bundle exec annotate

 Test Driven Development (3.2.1, 6.2.1)

  • Create a ‘request’ test for each static page (/spec/requests/…)
  • Create a model test for each model (/spec/models/…)

Adding migrations to an existing model (6.2.5)

rails generate migration add_index_to_users_email

Look for the new migration file and edit it appropriately. Then run:

bundle exec rake db:migrate

Example #2 (specifying a column to add to a table):

rails generate migration add_password_digest_to_users password_digest:string

Post migration creation:

$ bundle exec rake db:migrate
$ bundle exec rake db:test:prepare
$ bundle exec rspec spec/

Also, use add_index (8.2.1) to create an index on any column that will be used to retrieve info

Add debug info to a view (7.1.1)

<%= debug(params) if Rails.env.development? %>

Run console in a different environment (test/development/production) (box 7.1)

rails console test

Run server in a different environment (test/development/production) (box 7.1)

bundle exec rake db:migrate RAILS_ENV=production

Reset the database (7.2)

bundle exec rake db:reset

# "ensures that the data model from the development database is reflected in the test database" 
bundle exec rake db:test:prepare 

[restart Web server]

Completely clear and reset the data base (http://bit.ly/RL1HN1)

rake db:drop
rake db:create
rake db:migrate

Run a subset of rspec tests matching a string (7.4.4)

rspec -e "signup page"

Deploy to Heroku (7.4.4)

1. git push heroku
2. heroku run rake db:migrate
3. heroku open (opens the site in a browser)

Reset a Heroku DB (9.5)

$ git push heroku
$ heroku pg:reset HEROKU_POSTGRESQL_CHARCOAL_URL [probably]
$ heroku run rake db:migrate
$ heroku run rake db:populate

Making error messages more user friendly (7.6)

Flash messages vs. flash.now messages (8.15)

  • flash messages stay on the screen for one request (ex: redirect)
  • flash.now messages for one render. Goes away on next request.

Note about helpers

  • By default, all the helpers are available in the views but not in the controllers
  • So, it is necessary to explicitly include helpers within controllers

Cool shortcut to finding objects by a property (8.2.3 and elsewhere)

Object.find_by_property("str")
ex: User.find_by_name("Joel B")
ex: User.find_by_email("jberghoff@yahoo.com")

 Writing tests for checking cookie values (not a great idea) (8.2.6)

… experience shows that direct tests of cookie values are brittle and have a tendency to rely on implementation details that sometimes change from one Rails release to the next. The result is breaking tests for application code that still works fine. By focusing on high-level functionality—verifying that users can sign in, stay signed in from page to page, and can sign out—we test the core application code without focusing on less important details.

Visiting a typical page with RSpec:

before { sign_in user }

Visiting a path involving an update with RSpec (9.2.1)

before { put user_path(user) }

Note that direct use of the PUT HTTP request here. There’s no other way to do it.

Using exclamation points with actions (9.3.2)

  • create will return “false” if it doesn’t work
  • create! will raise an exception if it fails

Populating the DB with sample users (see section 9.3.2)

Adding a boolean field to a db table = awesome (9.4.1)

1. $ rails generate migration add_admin_to_users admin:boolean
2. Creates
      class AddAdminToUsers < ActiveRecord::Migration
        def change
          add_column :users, :admin, :boolean, default: false
        end
      end
3. Change line to: add_column :users, :admin, :boolean, default: false 4. This automatically creates test user.admin? test

Only attr_accessible attributes can be assigned through mass assignment (9.4.1)

A note about arrays in Ruby (10.1.4)

Array assignment in Ruby copies a reference to the array, not the full array itself, which means that changes to the original array also affect the copy.