Last night I spent way too much time getting this whole deal working for an initial deployment. Heroku has always been one of the easiest ways to get Rails applications on a server and running, but working on this new idea with Rails 3.1 and the rails-admin engine was a bit trying.

Tools used:
Rails 3.1 rc 0.5
Rails-admin
Devise
GVIM – Editor

If you have not used Rails-admin yet I suggest you check it out. The interface is highly intuitive and it creates a well designed admin for any CMS style application. Our application has a need for admins to do work in an area separate from the general signed in user. In other applications I have achieved this with roles and I see no difference here with the exception that I wanted to use rails-admin for the administrators and not the general user, or member.

The READMEs for devise and rails-admin setups are pretty good for set so I won’t go into them here.

Part One: The stupidness begins…

After the basic project is setup, the next thing I did was create a role field on the on the user column. In some applications this can be a boolean, but we may need many roles later one so I went with an integer.

#cmd-line
$ rails generate migration AddRolesToUsers
 
#gvim rails_app/db/migration/last_migration_bla_blah.rb
class ChangeUserRoleDefaulttoOne < ActiveRecord::Migration   def change     add_column :users, :role, :integer, :default => 1
  end
end
 
#cmd-line
$ rake db:migrate

Now I need to make the rails-admin area unreachable for users that are not administrators. Create a file in config/initializers/rails_admin.rb and add the following. The part that tricked me here was the “warden.user.role”. I assumed it would be something like current_user, foolish right!? Anyway this information is in the awesome readme of rails-admin at the very bottom.

#gvim config/initializers/rails_admin.rb
RailsAdmin.config do |config|
  config.authenticate_with do
    redircet_to root_path unless warden.user.role.eql?(3)
  end
end

Now I have an admin area that can only be accessed by admins. New users who create an account can only access pre-determined areas prefixed in the controller with basic devise authentication checks.

#gvim app/controllers/some_controller.rb
class SomeController < ApplicationController
 before_filter :authenticate_user! 
end

Except it doesn’t work! Apparently my sign_out path for devise is messed up. This has never been an issue before and I forget all the details, but here is the error and solution.

No route matches [GET] "/users/sign_out" devise 3.1 rails

WTF? When I run

$ rake routes

My link_to ‘Logout’ looks normal.

# app/views/layouts/application.haml.html
%p= link_to('Logout', destroy_user_session_path) if current_user

But… apparently with Rails 3.1 you need to configure the config/initializers/devise.rb

  # The default HTTP method used to sign out a resource. Default is :delete.
  config.sign_out_via = :get

Snap! Now that works.

Part Two: The stupidness continues…

Not even thinking the Heroku/Rails mix wouldn’t fire away the first time with no configuration I pulled one of these:

#cmd-line
$ heroku create my_app
$ git add .
$ git commit -m 'going to heroku'
$ git push heroku master

Things seemed ok, but the app won’t start quite yet

#cmd-line
$ heroku rake db:migrate

rake aborted! 

> Could not find a JavaScript runtime. See
> https://github.com/sstephenson/execjs
> for a list of available runtimes.

What is this? There is a Stackoverflow ticket about the issue here, but it doesn’t solve the issue. The solution describes adding this GEMFILE

group :production do
  gem 'therubyracer-heroku', '0.8.1.pre3'
end

This is not recommended by Heroku and leaves one to wonder how this new asset pipeline system is going to work on Heroku. Luckily Heroku has created a stack named Cedar, which is in beta, for Rails 3.1 applications. With this knowledge I start with a migration of my stack.

$ heroku stack:migrate cedar

But.. this doesn’t work either. In order to use the beta Cedar stack you have to create a new Cedar instance – no migrating allowed.

$ heroku create my_app_2 --stack cedar

Now edit your git config to point to your newly created Heroku app.

#cmd-line
$gvim .git

#.git/config
[core]
	repositoryformatversion = 0
	filemode = true
	bare = false
	logallrefupdates = true
	ignorecase = true
[remote "origin"]
	fetch = +refs/heads/*:refs/remotes/origin/*
	url = git@github.com:username/my_app.git
[branch "master"]
	remote = origin
	merge = refs/heads/master
[remote "heroku"]
	url = git@heroku.com:my_app_2.git
	fetch = +refs/heads/*:refs/remotes/heroku/*

Woot! getting closer, but don’t forget the ‘pg’ gem in your Gemfile. If you are using a DB other than ‘pg’ in development make sure you wrap that a development group in your gemfile too or Heroku with kick your app back.

#GEMFILE 
group :production do
  gem 'pg'
end
 
group :development do
  gem 'sqlite3'
end

We also need to add a path variable to our heroku config

  heroku config:add PATH=vendor/bundle/ruby/1.9.1/bin:/usr/local/bin:/usr/bin:/bin:bin

Try again

#cmd-line
$ git add .
$ git commit -m 'going to heroku'
$ git push heroku master
$ heroku run rake db:migrate //Cedar needs this extra "run" command 
$ heroku run db:push

Snap! Now I have my app, schema, data, and authentication set up on Heroku. That took way to long to figure out, too long to write this post, so I hope it finds someone and helps.

Lesson learned, “Don’t assume Heroku knows which stack to create with your application.” It doesn’t know and you have to know what you are deploying to make your specific application work.

One thought on “Deploying Rails 3.1 on Heroku Cedar with Rails Admin

  1. tb says:

    Thanks, this saved my brains when trying to deploy a Sinatra app with coffee-script and sprockets to heroku! I was getting that awful “Could not find a JavaScript runtime” error, and just switched to the cedar stack, and wham! Success. Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *