HTFramework

April 19th, 2010

HTFramework is a framework of re-usable components for happier iPhone OS development: http://github.com/huddletech/HTFramework/

Deploying a Hobo app to Heroku

December 28th, 2009

Hobo and Heroku make for a killer combination for getting your app built and deployed in record time.

These instructions are for Hobo 0.9.102. If you’re using an older version the steps may differ.

$ hobo myapp
$ cd myapp
$ git init
$ heroku create yourappname

Create a .gems file, since Hobo isn’t pre-installed on Heroku:

hobo --version 0.9.102

It is recommend to specify a particular version of any gem you use, in case a future release isn’t fully backwards compatible. (There’s no longer any need to specify will_paginate here.)

Next, create a .gitignore file:

log/*
db/*.sqlite3

Generate the database migrations:

$ script/generate hobo_migration

Choose [m] to migrate now and give it a name such as create users.

To generate the auto dryml files in app/views/taglibs/auto/, you’ll need to access the site once locally. Hobo cannot create these on Heroku because the filesystem is read-only. So run:

$ script/server

And open http://localhost:3000 in your browser.

You can then add all your files into the git repository, and push them to Heroku:

$ git add *
$ git add .gems
$ git add .gitignore
$ git commit -m "initial import" 
$ git push heroku master

It will take a couple of minutes to install the Hobo gem the first time you deploy, but subsequent deployments will be faster.

Next, run the database migration on Heroku:

$ heroku rake db:migrate

If you don’t see any error message, then you should be good to go:

$ heroku open

Common Problems

If you see the Rails “something went wrong” error, use heroku console to view the error log.

  • “relation “users” does not exist” – you probably forgot to run heroku rake db:migrate

Cucumber Scaffolding for Rails

December 27th, 2009

I recently discovered the rspec_scaffold generator, part of rspec_on_rails. It generates a resource just as the normal Rails one does, and rspec tests instead of normal tests, as the example below shows:

$ script/generate rspec_scaffold person name:string admin:boolean birthday:date
      exists  app/models/
      exists  app/controllers/
      exists  app/helpers/
      create  app/views/people
      exists  app/views/layouts/
      exists  public/stylesheets/
      exists  spec/controllers/
      exists  spec/routing/
      exists  spec/models/
      exists  spec/helpers/
      exists  spec/fixtures/
      create  spec/views/people
      exists  spec/integration/
      create  app/views/layouts/people.html.erb
   identical  public/stylesheets/scaffold.css
      create  spec/routing/people_routing_spec.rb
      create  spec/controllers/people_controller_spec.rb
      create  app/controllers/people_controller.rb
      create  spec/helpers/people_helper_spec.rb
      create  app/helpers/people_helper.rb
      create  app/views/people/index.html.erb
      create  app/views/people/show.html.erb
      create  app/views/people/new.html.erb
      create  app/views/people/edit.html.erb
      create  app/models/person.rb
      create  spec/fixtures/people.yml
      create  spec/models/person_spec.rb
      create  spec/views/people/edit.html.erb_spec.rb
      create  spec/views/people/index.html.erb_spec.rb
      create  spec/views/people/new.html.erb_spec.rb
      create  spec/views/people/show.html.erb_spec.rb
      create  spec/integration/people_spec.rb
      exists  db/migrate
      create  db/migrate/20091227214143_create_people.rb
       route  map.resources :people

But unlike the normal tests, these aren’t just skeleton files. They include a wide range of tests for the model and it’s controller, views and routes.

The thing that’s missing is an integration test, such as the following Cucumber feature:
Feature: Manage people

  Scenario: List people
    Given a person exists with name "Homer Simpson" 
      And a person exists with name "Bart Simpson" 
    When I go to the people page
    Then the title should be "People: index" 
      And the heading should be "Listing people" 
      And I should see "Homer Simpson" 
      And I should see "Bart Simpson" 

  Scenario: View person
    Given a person exists with name "Homer Simpson" 
    When I go to the people page
      And I follow "Show" 
    Then I should be on the page for that person
      And the title should be "People: show" 
      And I should see "Homer Simpson" against "Name:" 

  Scenario: New person
    Given I am on the people page
    When I follow "New person" 
    Then I should be on the new person page
      And the title should be "People: new" 
      And the heading should be "New person" 
      And the person's birthday should be today
      And the person's birthday year range should be from 5 years ago to 5 years from now

  Scenario: Create person
    Given I am on the new person page
    When I fill in "Name" with "Homer Simpson" 
      And I check "admin" 
      And I select "December 31, 2007" as the "Birthday" date
      And I press "Create" 
    Then I should be on the page for person "Homer Simpson" 
      And I should see "Homer Simpson" against "Name:" 
      And I should see "true" against "Admin:" 
      And I should see "2007-12-31" against "Birthday:" 
      And I should see "Person was successfully created." 

  Scenario: Back from new person page
    Given I am on the new person page
    When I follow "Back" 
    Then I should be on the people page

  Scenario: Back from edit person page
    Given a person exists with name "Homer Simpson" 
    When I go to the edit page for that person
      And I follow "Back" 
    Then I should be on the people page

  Scenario: Show from edit person page
    Given a person exists with name "Homer Simpson" 
    When I go to the edit page for that person
      And I follow "Show" 
    Then I should be on the page for that person

  Scenario: Edit from show person page
    Given a person exists with name "Homer Simpson" 
    When I go to the page for that person
      And I follow "Edit" 
    Then I should be on the edit page for that person

  Scenario: Edit person
    Given a person exists with name "Homer Simpson" 
      And that person is admin
      And that person has "birthday" date "February 14, 2010" 
    When I go to the people page
      And I follow "Edit" 
    Then I should be on the edit page for that person
      And the title should be "People: edit" 
      And the heading should be "Editing person" 
      And the "name" field should contain "Homer Simpson" 
      And the "admin" checkbox should be checked
      And the person's birthday should be "February 14, 2010" 

  Scenario: Update person
    Given a person exists with name "Homer Simpson" 
      And that person is admin
    When I go to the edit page for that person
      And I fill in "name" with "Homer J Simpson" 
      And I uncheck "admin" 
      And I press "Update" 
    Then I should be on the page for person "Homer J Simpson" 
      And I should see "Person was successfully updated." 
      And I should see "Homer J Simpson" against "Name:" 
      And I should see "false" against "Admin:" 

I wrote the above manually but I plan to automate this and turn it into a gem eventually, so that you’ll be able to do something like this:

$ script/generate cucumber_scaffold person name:string admin:boolean birthday:date

Installing Mephisto on Heroku

December 26th, 2009

Since Heroku apps run in a read-only filesystem, the normal Mephisto installation method won’t work. Here’s how to work around that.

Begin by cloning Mephisto in the usual way:

$ git clone git://github.com/emk/mephisto.git
$ cd mephisto

And prepare the database configuration:

$ cp config/database.example.yml config/database.yml

Normally the next step would be to run rake db:bootstrap which modifies and creates a few files. Since we can’t do this on Heroku, we’ll create them locally and add them to the respository.

The behaviour in the development environment differs from production, so we need to run in production mode locally.

If you have mysql running setup, create a new database named mephisto_production. Alternatively, just define a sqlite connection:

production:
  adapter: sqlite3
  database: db/mephisto_production

You can now bootstrap the app:

$ rake db:bootstrap RAILS_ENV=production

This will modify session_store.rb and create a few other files/folders, but git status won’t show them since they are excluded by .gitignore. Use the -f flag to force add them:

$ git add config/initializers/session_store.rb -f
$ git add themes/ -f
$ git add public/plugin_assets/ -f
$ git commit -m "adding required files for Heroku" 

You’re now ready to deploy onto Heroku:

$ heroku create yourblogname
$ git push heroku master
$ heroku rake db:bootstrap

I’m not sure why, but at this point you need to restart your app or you’ll get an error message:

$ heroku restart

You can then view the site in your browser and you should see Mephisto running.

$ heroku open

Notes

  1. The above instructions will deploy the edge version of Mephisto rather than the v0.8-stable branch which the official site recommends, but I haven’t yet worked out how to deploy a particular branch to Heroku.
  2. Some features will not work on Heroku, such as installing/editing themes or uploading assets. You will need to do this locally and then add the appropriate files to the git repository.