Hello, I'm James. I'm a professional Ruby on Rails developer with seven years experience: I created Hyper and I work exclusively with Ruby. Hire me to work on your web app.


Paperclip On Heroku With Amazon S3

Today I'm making paperclip_heroku available: this gem makes it super easy to configure Paperclip on Heroku using Amazon S3. It will also switch automatically between S3 storage in production and filesystem storage in development/test environments.

Here's how to get up and running:

# in Gemfile
gem 'paperclip_heroku'

# in your models
class User < ActiveRecord::Base
  has_attached_file :avatar, heroku: true

It's that simple. Read the documentation for more configuration options and file an issue if you have feedback.


Why I Love Instagram

Everything's better when you concentrate. Fewer mistakes, more originality, and (if you do it right) a better state of mind. That's why I love Instagram: it forces me to focus.

Every Instagram photo is the same size. Every Instagram photo has the same dimensions. I get the same choice of filters every time. I don't miss iPhoto's adjustment options: they just slowed me down.

I started using Instagram again recently because I wanted to get back into photography. If I do things right, I can take a photo, make adjustments, save it, and share it inside a minute. That's a great way to learn: practice often, make mistakes fast, learn, get better.


Case-Insensitive Searches With PostgreSQL

Most Rails developers will have used one or both of MySQL and SQLite for development work. In both of these flavours of SQL, the like operator performs case-insensitive searches.

This example from the MySQL documentation is a good illustration of how this works:

The default character set and collation are latin1 and latin1_swedish_ci, so nonbinary string comparisons are case insensitive by default. This means that if you search with col_name LIKE "a%";, you get all column values that start with A or a.

Let's assume that you want this behaviour.

If, like a lot of Rails developers, you use Heroku for hosting or staging, you'll run into a problem: Heroku uses PostgreSQL, and PostgreSQL's like is case-sensitive. In practice, this means that you'll test your code in development, deploy to Heroku, and see different results. How to fix this?

This fix is simple: PostgreSQL provides an ilike operator which performs case-insenstive searches (the behaviour for ilike is the same as for like in MySQL and SQLite). So, we can check which SQL adaptor Rails is using and use either like or ilike as appropriate.

Here's an example in an ActiveRecord scope:

scope :search, lambda { |phrase|  
  if connection.adapter_name == 'PostgreSQL'
    where("title ilike ?", "%#{phrase}%")
    where("title like ?", "%#{phrase}%")

This gives us the correct behaviour whatever flavour of SQL we're using.


Hyper 0.4.2 Released

Version 0.4.2 of Hyper, my framework for small HTML websites, fixes a bug that stopped new sites from having a public folder. Grab the code from Github or install via Rubygems:

$ gem install hyper

If you're coming to Hyper for the first time and want to see what it can do, try the edge of space map.


It's Not About The Settings

I remember the first time I used Windows properly: there were lots of settings. Pages and pages of settings. Entire magazines made a profit from explaining how people could, and should (and should not) use the settings to do, well, anything. Want to read your email only on Tuesdays in March? There's a setting for that.

There is, I think, something called the poverty of choice: when you can do anything, it's hard to do something. For a long, long time personal computing used choice as a benchmark: the more options you were given, the better a piece of software or hardware was. This led, inevitably, to companies Dell and their confusing array of PC options.

Choice is good for experts. I want to decide which album to listen to this evening; I am an expert on my music collection. But I don't want to do the detailed research to work out what album to buy next: that's what iTunes reviews are for. The vast invisible mass of iTunes reviewers does my thinking for me.

Most people are not experts. Most people have too much choice. Most people, myself included, want to be guided when they're on unfamiliar ground. And this is where the personal computing industry failed until recently: it assumed that normal people like my mum wanted a level of choice which (with respect to my mum) they really couldn't — and didn't want to, didn't need to — handle.


How To Restart Postgres On Homebrew

Sometimes when running RSpec against a Postgres database I find unused sessions hanging around which block access to the test database:

PG::Error: ERROR: database "postgres_test" is being accessed by other users
DETAIL:  There are 1 other session(s) using the database.

Restarting Postgres is the best way I know to clear out all sessions:

$ launchctl unload -w ~/Library/LaunchAgents/homebrew.mxcl.postgresql.plist 
$ launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.postgresql.plist


Why You Won't Build The Next Basecamp And Why It Doesn't Matter

When I started work as a web developer, back in 2005, Basecamp was the big new thing — web apps in general were the big new thing. Ambitious developers wanted to "build the next Basecamp", and that's a phrase I still hear today, six years after Basecamp became popular.

Building the next Basecamp is a pointless aim for any startup, and here's why. First, the target is too vague: "the next Basecamp", what does that mean? Basecamp came along when web apps were fresh and new, and the web app market was young enough to have room for big, generic products which covered a lot of ground — Basecamp is essentially a project management tool aimed at a very broad market.

Now the web app market is more mature, you're more likely to be successful if you niche down and build something that targets a very specific audience. You might make less money, but at least you'll make some money (and you'll stand a much better chance of making that "some" into something significant).

Second, "build the next Basecamp" is too often used as a lazy stand in for "make lots of money with a web app". Don't mistake effect for cause: "make a lot of money" is an OK goal in itself, but you won't achieve that goal just by wanting to achieve it — I don't care how much pop psychology you read. You'll get to your goal by making something good that sells!

Third (and this is most important, even if you don't think it is): if you're talking about building "the next Basecamp" then any spark of creativity you might have will be drowned by your (probably subconscious) desire to blindly copy the people who have already got to where you want to be. Read Rework, learn Rails, build a web app… it worked for them so why not for me?

The only problem: success comes from inspiration, not from duplication. Forget what's happened before and use your own ideas: they're the only chance you've got.



When I woke up on the morning of October 6th, I visited Apple blog Daring Fireball and saw a deep black background in place of the usual grey. That can't be good, I thought: someone has died. Then I saw the headlines.

When someone in Steve Jobs' position dies, two things happen: first, the person's friends and family suffer; second, the person's achievements are celebrated, picked over, and the person is — often — idolised. That day, I watched the second of those things happen, and imagined the first.

My family has suffered two deaths from cancer in the past few years, and I know that whatever someone has achieved in their life their death still feels as painful as you could imagine. Everyone achieves something important, whether it's battling cancer, raising children, or changing personal technology for the better: we all deserve to be remembered and celebrated for the difference we make in the world.

But Steve Jobs' real legacy isn't an unreachable plateau of genius: it's the example he set, an example of someone who believed in himself, trusted his instincts, and had the courage to do what he thought was right. That's something we can all achieve, in our own ways, if we remember what's really important.

Here's an excerpt from Jobs' widely-quoted Stanford commencement address:

Remembering that I'll be dead soon is the most important tool I've ever encountered to help me make the big choices in life. Because almost everything - all external expectations, all pride, all fear of embarrassment or failure - these things just fall away in the face of death, leaving only what is truly important. Remembering that you are going to die is the best way I know to avoid the trap of thinking you have something to lose. You are already naked. There is no reason not to follow your heart.

The best way to celebrate someone's life is to learn from it.


Hyper: A Framework For Ruby Websites

Hyper is a micro-framework that supports small, static HTML sites with some Ruby magic thrown in. Its focus is on building and launching a site fast: there's zero configuration, no route definitions, and definitely no databases.

Why Build Hyper?

I could have used Sinatra or Rails for my personal projects, but I wanted something lighter. I wanted a framework that could take me from a standing start to a functioning website without any configuration (even Sinatra's get '/url' route definitions felt like they were holding me back).

Most importantly, I wanted the experience that comes from building something for myself.

Quick Start

$ gem install hyper
$ hyper new cool_site
$ cd cool_site
$ bundle install
$ bundle exec rackup

Your new site is now live at


I want Hyper to hit the sweet spot between plain HTML (no Ruby) and dynamic frameworks like Rails. Route-to-template mappings are automatic:

/	# templates/views/index.html.erb
/about	# templates/views/about.html.erb
/help	# templates/views/help.html.erb

Because Hyper does this automagically, you can just drop my content into the correct file and move on. Every URL is handled in this way, and there are no exceptions: this behaviour covers 99% of my needs, and if I want something more dynamic I can use a different framework.


Because this is a Ruby framework, you get a helper module:

# in lib/helper.rb
module Hyper::Helper
  def say_hello
    "Hello world"

# in templates/views/hello.html.erb
<p><%= say_hello -%></p>

And because it makes sense to split HTML into layout and views, Hyper does just that: shared HTML lives in templates/layout.html.erb, and page-specific content lives in templates/views.

Fast Deployment With Heroku

Ruby developers have an amazing hosting service in Heroku: prices start at free and the platform supports any web app that's based on Rack. Can you guess what Hyper is based on?

$ cd cool_website
$ heroku create
$ git push heroku master
-----> Heroku receiving push
-----> Rack app detected

Boom: your website is now on the web.

Share And Enjoy

Hyper is available on Github and via Rubygems: right now it's working great for me; I hope it works for you too.