Thursday, March 18, 2010

Getting Rails 3.0 running with “My Stack” on Ruby 1.9.1

I’m pretty excited about Rails 3.0. It really feels like a polished version of the framework, much like Snow Leopard was for Leopard OS X.

At this stage in the game I really don’t want to be starting any new projects with Rails 2.3.5, so I thought I would see if it was possible to get Rails 3.0-beta running with “My Stack”—a set of gems/plugins used on all of my projects. Admittedly, there are probably some others that I should be using, but these are definitely the essentials:

  • haml (with sass)
  • compass
  • authlogic
  • shoulda
  • factory_girl
  • will_paginate

Just to keep things interesting I thought I would throw Ruby 1.9.1 in there to mix things up.

First, stop was to check out A registry setup by Engine Yard to track which plugins are Rail 3, Thread Safe, JRuby, and Ruby 1.9 compatible. Let’s see how my stack faired (note, I’m only interested in Rails 3 and Ruby 1.9):

OK, let’s look at each plugin, step by step:

Haml (Confirmed to work)

Installing Haml was pretty straight forward:

# Gemfile
gem "haml", "2.2.21" 

# command line (rails root of course)
bundle install
haml --rails . 

Compass (Confirmed to work)

Install Compass was also straight forward:

# Gemfile
gem "compass", "0.10.0.pre9" 

# command line
compass --rails -f blueprint . --css-dir=public/stylesheets/compiled --sass-dir=app/stylesheets

Authlogic (Unknown to work)

While Authologic is officially “not working”, reports from end users suggest it is. Following along with Ryan Bates screencast, you just need to translate the script/generate commands to rails generate and also check for new options. To setup Authlogic with your application, add it to your Gemfile.

# Gemfile
gem "authlogic", :git => "git://" 

Shoulda (Unknown to work)

There are no reports regarding shoulda (as there is no version number assigned to, and you can't comment without a version number). Although there is a rails3 branch, it hasn’t been touched since mid-January. Well let’s give it a go and see how far we get:

# Gemfile
gem "shoulda", :git => "git://", :branch => "rails3", :group => :test

A couple of options to note. :branch specifies the branch of the git repo, and :group the environment. You won’t be needing shoulda in production.

So how did we get on? Trying rake test... Boom!

DEPRECATION WARNING: RAILS_ROOT is deprecated! Use Rails.root instead. (called from join at ~/.bundle/ruby/1.9.1/bundler/gems/shoulda-b78dbf514bbce3272023d3a4742474857c2eb3c3-rails3/lib/shoulda/autoload_macros.rb:40)
  ~/.bundle/ruby/1.9.1/bundler/gems/shoulda-b78dbf514bbce3272023d3a4742474857c2eb3c3-rails3/lib/shoulda/autoload_macros.rb:40:in `join': can't convert #<Class:0x1297f3c> into String (TypeError)  

OK, let’s remove shoulda gem from:

rm -rf ~/.bundle/ruby/1.9.1/bundler/gems/

And let’s try a more up to date fork. This looks like it:

# Gemfile
gem "shoulda", :git => "git://", :branch => "rails3", :group => :test

You get this message but it doesn’t appear to be anything to worry about (I hope):

shoulda at ~/.bundle/ruby/1.9.1/bundler/gems/shoulda-87e75311f83548760114cd4188afa4f83fecdc22-rails3 did not have a valid gemspec.
  This prevents bundler from installing bins or native extensions, but that may not affect its functionality.
  The validation message from Rubygems was:
    ["test/rails_root/db/development.sqlite3", "test/rails_root/doc", "test/rails_root/log/development.log", "test/rails_root/log/production.log", "test/rails_root/log/server.log", "test/rails_root/log/test.log", "test/rails_root/test/fixtures", "test/rails_root/test/functional", "test/rails_root/test/integration", "test/rails_root/test/unit"] are not files

And running rake test works. Let’s convert a controller over.

context "create card" do
    setup { post :create, :card => cards(:one).attributes }

    should_change "Card.count", :by => 1
    should_redirect_to("new card") { card_path(assigns(:card)) }

Almost works, but dies on the should_change marco.

1) Error:
test: create card should change Card.count by 1. (CardsControllerTest):
NoMethodError: undefined method `call' for #<Arel::Value:0x172eba8>
      ~/.bundle/ruby/1.9.1/bundler/gems/shoulda-87e75311f83548760114cd4188afa4f83fecdc22-rails3/lib/shoulda/macros.rb:45:in `block in should_change'
      ~/.bundle/ruby/1.9.1/bundler/gems/shoulda-87e75311f83548760114cd4188afa4f83fecdc22-rails3/lib/shoulda/context.rb:360:in `call'
      ~/.bundle/ruby/1.9.1/bundler/gems/shoulda-87e75311f83548760114cd4188afa4f83fecdc22-rails3/lib/shoulda/context.rb:360:in `block in create_test_from_should_hash'  

Looks like a change in ActiveRecord is causing a few problem there.

Conlusion on Shoulda: OK, it might be the only macro failing, but I think at this stage i will leave shoulda at this point. I’ve filed an issue and if I have some time I will look into it myself.

Factory Girl (Unknown to work)

While the owner says it’s “not working”. A commentator says it does. Let’s give it a go:

# Gemfile
gem 'factory_girl', :git => 'git://', :branch => 'rails3', :group => :test

# command line
bundle install

And convert a controller over to use factories instead of fixtures (yuk!).

# factories.rb

Factory.define :card do |c| 'Lorem ipsum dolor sit amet'

# cards_controller_test.rb
require 'test_helper'

class CardsControllerTest < ActionController::TestCase

  setup do
    @card = Factory(:card)    

  test "should get index" do
    get :index
    assert_response :success
    assert_not_nil assigns(:cards)

  test "should get new" do
    get :new
    assert_response :success

  test "should create card" do
    assert_difference('Card.count') do
      post :create, :card => @card.attributes

    assert_redirected_to card_path(assigns(:card))

  test "should show card" do
    get :show, :id => @card.to_param
    assert_response :success

  test "should get edit" do
    get :edit, :id => @card.to_param
    assert_response :success

  test "should update card" do
    put :update, :id => @card.to_param, :card => @card.attributes
    assert_redirected_to card_path(assigns(:card))

  test "should destroy card" do
    assert_difference('Card.count', -1) do
      delete :destroy, :id => @card.to_param

    assert_redirected_to cards_path

Yes, it’s a very simple example of using a factory. So there might be some bugs lurking around. But I’m guess it’s safe to say this is usable.

Will Paginate (Confirmed to work)

This looks promising.

# Gemfile
gem "will_paginate", "3.0.pre"  

# command line
bundle install

Again, it’s a simple example, but I think it’s safe to say we’re good to go.

# cards_controller.rb
@cards = Card.paginate :page => params[:page], :per_page => 1

# index.html.haml
= will_paginate @cards


Well it is marked Beta for a reason—and that’s for the gem/plugin ecosystem to catch up. With my limited playing with Rails 3-beta I would be confident writing applications with it, and while most plugins seem to be compatible, I feel a little uneasy doing production projects until there is a broader range of plugins compatible with it. Looks like I will be staying with Rails 2.3.5 a little longer.

Wednesday, March 17, 2010

Get Sass and Compass running on Heroku with Rails 3.0-beta

Heroku is read-only file system causing a little havoc for runtime compilation of Sass files into CSS. In my recent trial of running a Rails 3.0-beta application on Heroku with MRI 1.9.1 I came across this issue.

Doing a google on “heroku sass” will bring you to this post which leads you to sass_on_heroku plugin which is deprecated. The current plugin is Hassle, but unfortunately this hasn’t been touched for a few months. There are some current issues with this plugin and Compass. But all is not lost! Jacques Crocker has forked the plugin and made a fix for this. Get a compatible version of Hassle that works with Compass from his repo.

Now, there’s one change that needs to be made to get Hassle working with Rails 3.0-beta. As Hassle is a piece of Rack middleware, the configuration has changed and must be configured using the Railtie class based on this documentation. Admittedly, this is a little hacky, but gets things going. Placing the Railtie file in it’s own file and namedspace would clean things up.

# init.rb

# Rails 2.3.x style
# if RAILS_ENV == 'production'
#   ActionController::Dispatcher.middleware.use Hassle
# end

require 'hassle'

class HassleRailtie < Rails::Railtie
  config.middleware.use Hassle if Rails.env == 'production' 

And, that’s it! With this you should be able to get Sass and Compass running on Heroku with Rails 3.0-beta.

Getting Rails 3.0-beta running on Heroku

I wanted to test out Rails 3.0-beta and see how far I could get with developing an application with my stack of gems/plugins. I hadn’t checked out Heroku either, so it gave me an opportunity to try out their new stacks with Ruby 1.9.1.

First, I installed Rails 3 Beta and RVM outlined in Ryan Bate’s screencast. If you haven’t installed RVM yet, you will be wondering why it’s taken you this long. I did.

Once you have Rails up and running, you can following with their quick start guide. There’s a couple of things to take note when deploying for Rails 3.0-beta, but it’s all pretty straight forward.

As mentioned in the documentation you will need to add the “pg” gem to your Gemfile as Heroku runs Postgres database on their servers; i.e. not MySQL.

  # Gemfile
  group :production do
    gem "pg" 

By placing it in the “production” group you won’t need to install it locally.

I’m super impressed by Heroku, and look forward to get a production application running on their platform. It’s simply awesome.

Monday, March 15, 2010

Focus Website Content on your Customers' Knowledge Gap

The biggest hurdle when developing a website is producing the content. All of us who have experienced the process of launching a website will probably agree that it was the content development stage that dragged out forever, that delayed the launch. Even deciding what content should be on the site is difficult. Over the last two posts1, I have highlighted the importance on focusing on your customer first, and outlined strategies to identify their needs.

Identify your customer’s knowledge gap

Another strategy is to identify your customers’ knowledge gap. The concept of the knowledge gap was presented by Jared Spool (of UIE fame) in his presentation “What Users Want”2. The knowledge gap is the gap between two points on a spectrum, the current knowledge and the target knowledge.

Picture 1.png

The current knowledge is the information your customer already knows about your business domain: your company, service, product, industry and market. The target knowledge is what your customer needs to know to make a decision.

Spool suggests your website content targets the knowledge gap. It is a wasted effort to develop content before current knowledge and after target knowledge.

How to find the knowledge gap?

A quick start on identifying your customers’ knowledge gap is to create two lists side-by-side. List 20 items your customer knows about what you are trying to sell—their current knowledge. Then, list 20 items your customer needs to know to make a decision—their target knowledge. You can help refine this list by visiting forums where your customers engage, and observe the questions that are being asked.

What is your customers’ knowledge gap?

[1] Create a Sketch of your Customers’ Needs and Ask 20 Questions to Build Customer Empathy

[2] What Users Want

Please note this blog is no longer maintained. Please visit CivilCode Inc.