Recent Posts

Subdomain accounts with Ruby on Rails explained

January 11, 2009

DHH recently posted, How to do Basecamp-style subdomains in Rails on SvN and it just happens that I was implementing some similar stuff this last week for a project we’re developing internally.

In our project, not everything needs to be scoped per-account as we are building a namespace for administrators of the application and also want a promotional site for the product. Three different interfaces, with some overlap between them all.

Let’s walk through a few quick steps that you can follow to setup the two interfaces within the same application.

Suppose that we’re going to build a new web-based product and have the following requirements initially.

  • We need a promotional site for sign-ups, frequently-asked-questions, support requests, etc.
  • When people sign-up for an account, they’ll should have their own unique sub-domain
  • There are two different visual layouts (promotional site and the account)

Note: I use RSpec and am going to skip the TDD process here and let you conquer that for yourself. Am using the default Rails commands in this tutorial.

Account model / Database

We’re going to generate a new model for Account, which will be responsible for scoping sub-domains and individual accounts.


account-demo : ruby script/generate model Account subdomain:string{lang=”ruby”}
create app/models/{lang=”ruby”}
create test/unit/{lang=”ruby”}
create test/fixtures/{lang=”ruby”}
create app/models/account.rb{lang=”ruby”}
create test/unit/account_test.rb{lang=”ruby”}
create test/fixtures/accounts.yml{lang=”ruby”}
exists db/migrate{lang=”ruby”}
create db/migrate/20090111220627_create_accounts.rb{lang=”ruby”}\

Great, let’s migrate our application.


account-demo : rake db:migrate{lang=”ruby”}
CreateAccounts: migrating = -- create_table(:accounts) -> 0.0045s CreateAccounts: migrated (0.0052s){lang=”ruby”}\

Before we get too far, let’s make sure that we’re adding an index on this table for the subdomain, as it’ll improve performance in the database as the subdomain will used in SQL conditions quite often.


account-demo : ruby script/generate migration AddIndexToAccountSubdomain{lang=”ruby”}
exists db/migrate{lang=”ruby”}
create db/migrate/20090111221009_add_index_to_account_subdomain.rb{lang=”ruby”}\

Let’s open up this new migration file and toss in a UNIQUE INDEX on subdomain.


class AddIndexToAccountSubdomain < ActiveRecord::Migration
def self.up
add_index :accounts, :subdomain, :unique => true
end

def self.down
remove_index :accounts, :subdomain
end
end\

Okay, let’s migrate this bad boy.


account-demo : rake db:migrate{lang=”ruby”}
AddIndexToAccountSubdomain: migrating = -- add_index(:accounts, :subdomain, {:unique=>true}) -> 0.0047s AddIndexToAccountSubdomain: migrated (0.0050s){lang=”ruby”}\

Great, we’re now ready to move on to the fun stuff.

Let’s open up app/models/account.rb and throw some sugar in it.

Data Validation

Because we’re going to be dealing with subdomains, we need to make sure that we’re only allowing people to sign-up with valid data otherwise, there could be issues. URLs need to fit within certain conventions and we need to make it as graceful as possible for our customers.

Let’s make a quick list of what we need to enforce for the subdomain attributes. This can easily be expanded, but let’s cover the basics.

  • Each account should have a subdomain
  • Each subdomain should be unique within the application
  • A subdomain should be alpha-numeric with no characters or spaces with the exception of a dash (my requirement)
  • A subdomain should be stored as lowercase

So, let’s update the following default Account model….


class Account < ActiveRecord::Base{lang=”ruby”}
end{lang=”ruby”}\

..and add some basic validations.


class Account < ActiveRecord::Base
validates_presence_of :subdomain
validates_format_of :subdomain, :with => /\^[A-Za-z0-9-]+$/, :message => ‘The subdomain can only contain alphanumeric characters and dashes.’, :allow_blank => true
validates_uniqueness_of :subdomain, :case_sensitive => false

before_validation :downcase_subdomain

protected

def downcase_subdomain
self.subdomain.downcase! if attribute_present?(“subdomain”)
end
end\

Reserved subdomains

In the project that our team is working on, we wanted to reserve several subdomains so that we could use them later on. We tossed in the following validation as well.


validates_exclusion_of :subdomain, :in => %w( support blog www billing help api ), :message => “The subdomain {lang=”ruby”}``{lang=”ruby”} is reserved and unavailable.”{lang=”ruby”}\

This will prevent people from using those when they sign up.

Controller / Handling Requests

Let’s now think about how we’ll handle requests so that we can scope the application to the current account when a subdomain is being referenced in the URL.

For example, let’s say that our application is going to be: http://purplecowapp.com/ [^1^](#fn1){#fnref1 .footnote-ref role=”doc-noteref”}

Customers will get to sign-up and reserve http://customer-name.purplecowapp.com/. I want my account subdomain to be green.purplecowapp.com and everything under this subdomain should be related to my instance of the application.

I’ve begun working on my own module, which is inspired mostly by the account_location plugin with some additions to meet some of our product’s requirements.

Here is my attempt to simplify it for you (removed some other project-specific references) and have put this into a Gist for you.


#
# Inspired by
# http://dev.rubyonrails.org/svn/rails/plugins/account_location/lib/account_location.rb
#
module SubdomainAccounts
def self.included( controller )
controller.helper_method(:account_domain, :account_subdomain, :account_url, :current_account, :default_account_subdomain, :default_account_url)
end

protected

# TODO: need to handle www as well
def default_account_subdomain
‘’
end

def account_url( account_subdomain = default_account_subdomain, use_ssl = request.ssl? )
http_protocol(use_ssl) + account_host(account_subdomain)
end

def account_host( subdomain )
account_host = ‘’
account_host << subdomain + ‘.’
account_host << account_domain
end

def account_domain
account_domain = ‘’
account_domain << request.domain + request.port_string
end

def account_subdomain
request.subdomains.first || ‘’
end

def default_account_url( use_ssl = request.ssl? )
http_protocol(use_ssl) + account_domain
end

def current_account
Account.find_by_subdomain(account_subdomain)
end

def http_protocol( use_ssl = request.ssl? )
(use_ssl ? “https://” : “http://”)
end
end\

View gist here (embed wasn’t working right when I tried)

Just include this into your lib/ directory and require it in config/environment.rb. (if people think it’s worth moving into a plugin, I could do that)

Including AccountSubdomains

In the main application controller (app/controllers/application.rb), just include this submodule.


class ApplicationController < ActionController::Base
include SubdomainAccounts

…
end\

Now, we’ll want to add a check to verify that the requested subdomain is a valid account. (our code also checks for status on paid memberships, etc… but I’ll just show a basic version without that)

Let’s add in the following to app/controllers/application.rb. This will only check on the status of the account (via subdomain) if the current subdomain is not the default. For example: purplecowapp.com is just our promotion site, so we won’t look up the account status and/or worry about the subdomain. Otherwise, we’ll check on the status.


before_filter :check_account_status

protected
def check_account_status
unless account_subdomain == default_account_subdomain
# TODO: this is where we could check to see if the account is active as well (paid, etc…)
redirect_to default_account_url if current_account.nil?
end
end\

Current Account meets Project model

When requests are made to an account’s subdomain, we want to be able to scope our controller actions.

WARNING: I’m going to gloss over the following steps because this is just standard Rails development stuff and I want to focus on how to scope your Rails code to account subdomains.

I’ll just say that this product gives each account many projects to do stuff within. I’ll assume that you’ll know how to handle all that and we’ll assume you have a Project model already.

What you will need is to add a foreign key to your table (projects in this example) that references Account. So, make sure that your model has an account_id attribute with and that the database table column has an INDEX.

We’ll add our associations in the models so that they can reference each other.


# app/models/account.rb
class Account < ActiveRecord::Base
has_many :projects
# …
end

# app/models/project.rb
class Project < ActiveRecord::Base
belongs_to :account
# …
end\

Okay great… back to our controllers. The SubdomainAccounts module provides you with the current_account variable, which you can use within your controllers/views. This allows us to do the following in our controllers. For example, if we had a ProjectsController.


class ProjectsController < ApplicationController
def index
\@projects = current_account.projects.find(:all)
end

def new
\@project = current_account.projects.new
end

def show
\@project = current_account.projects.find(params[:id])
end

# …
end\

See, this wasn’t so hard, was it?

Handling layouts

I wanted to highlight one other thing here because I suspect that most projects that fit this will likely need a promotional/resource site where people will sign-up from. In our application, we have two application layouts. One for the main application that customers will interact with via their subdomain and the promotional site layout.

The default layout is just app/views/layouts/application.html.erb and we have our promotional site layout at app/views/layouts/promo_site.html.erb. A few of our controllers are specifically for the promotional site while the rest are for the application itself and in some cases, there is some overlap down to individual action within a controller.

What we did was add a few more before filters to our application controller to a) define the proper layout to render, and b) skip login_required on the promo site.

To have the proper layout get rendered, we’re just checking whether the current request was made to the promotional site or not.


class ApplicationController < ActionController::Base
# …
layout :current_layout_name # sets the proper layout, for promo_site or application

protected

def promo_site?
account_subdomain == default_account_subdomain
end

def current_layout_name
promo_site? ? ‘promo_site’ : ‘application’
end

# …
end\

Our application is using Restful Authentication and we just want to check to see if the current request is made to the promotional site or not. If it is, we’ll skip the login_required filter. Let’s assume that you have the following before_filter set.


class ApplicationController < ActionController::Base{lang=”ruby”}
# …{lang=”ruby”}
before_filter :login_required{lang=”ruby”}\

We’ll just change this to:


class ApplicationController < ActionController::Base
# ..
before_filter :check_if_login_is_required

protected
def promo_site?
account_subdomain == default_account_subdomain
end

def current_layout_name
promo_site? ? ‘promo_site’ : ‘application’
end

def check_if_login_is_required
login_required unless promo_site?
end

# …\

There we go. We can now render the proper layout given the request and only handle authentication when necessary.

Development with account subdomains

When you begin developing an application like this, you need to move beyond using http://locahost:3000 as we need to be able to develop and test with subdomains. You can open up your /etc/hosts (within a Unix-based O/S) file and add the following.

```
127.0.0.1 purplecowapp.dev
127.0.0.1 green.purplecowapp.dev
127.0.0.1 sample.purplecowapp.dev
127.0.0.1 planetargon.purplecowapp.dev
127.0.0.1 lollipops.purplecowapp.dev
127.0.0.1 help.purplecowapp.dev
127.0.0.1 support.purplecowapp.dev
```

After you edit that file (with root permissions), you can flush your dns cache with dscacheutil -flushcache (Mac OS X). This will let you make requests to http://purplecowapp.dev:3000/ and http://green.purplecowapp.dev:3000. This is a convention that our team has begun using for our own projects (TLD ending in .dev). It’s important to remember that the subdomain must be specified here in order to work for local requests. Unfortunately, hosts files don’t support wildcards (‘*’).

Update

You can also use Ghost, which is a gem for managing DNS entries locally with Mac OS X. Read Get to know a gem: Ghost

Summary

I know that I glossed over some sections, but was hoping that the code itself would be the most beneficial for you. Feel free to leave any questions and/or provide some feedback on our approach. Perhaps you have some suggestions that I could incorporate into this so that we can improve on this pattern.


  1. ::: {#fn1} yeah, I’ve been reading more Seth Godin recently…↩︎{.footnote-back role=”doc-backlink”} :::

Rails and Business in the 2009 World

January 10, 2009

The past few months have been difficult for many companies and as a result, some have had layoffs and now there are developers out there looking for new opportunities. I’ve received a few emails from friends and acquaintances in the Ruby on Rails community from people who are hoping to make it as a freelancer until another opportunity comes along. Questions ranging from hourly rates to managing clients has come up. I’m more than happy to offer people advice on this front but always try to invite them to solicit ideas and feedback from a larger group of people. We just happen to have an open forum for all of you that are interested in discussing business-related topics.

Two years ago, I started the Ruby on Rails meets the business world group on Google, which currently consists of nearly 900 members.

So, if you’re an entrepreneur and looking to engage with other business owners, freelancers, or to just listen in on the discussions out of curiosity, don’t hesitate to join the group. There are several of us that would love to share our experiences/lessons with you and also learn from others.

I’d invite you all to check out the discussion archives and start a dialogue with us.

…and as always, if you’re not ready for a bigger group, feel free to drop me a line personally.

Managing your Life the Agile Way in 2009

December 28, 2008

We’re just a few days away from 2009 and it’s that time when we all start looking back at the last year and set goals for the coming new year. I felt like sharing some of my thoughts on how I’m aiming to approach the new year.

Historically, I’ve never been a huge fan of New Years Resolutions because my attempts were always too big to successfully measure. The goals themselves weren’t poorly thought-out, it’s just that it’s really easy to make a list of personal targets, without putting a lot of emphasis on how you’re going to achieve them. The biggest trouble that I’ve had with goals is allocating enough mental energy for implementation planning. (if only I had someone to and wireframe my life…)

Due to this, New Years Resolutions haven’t been a huge success for me. I’ve found it much too easy to pass the buck onto the usual suspects, which consist of: lack of time, energy, too much work, general life changes, health, etc.

So, for 2009… I’m going to try something different by focusing on a set of best practices that I can use on a daily-basis. I suppose that my main goal is to not place too much emphasis on any specific targets and instead place the responsibility on myself to follow these best-practices and see what good (or bad) comes of it.

By rephrasing my internal conversation from, “What did I achieve this last year?” to “Am I doing things the best that I can?” I am confident that the answer will usually be, “not likely.” I do believe that through this subtle change in context, I’ll be better apt to self-evaluate how (and why) I am doing the things that I do and refactor accordingly. If we’re not consistently Refactoring ourselves (as we do with our code), we’re going to retain a lot inefficiencies in our personal and work lives, which make it difficult for us to quickly respond to changes and opportunities.

Our life (personal and work) is just another project that we manage. Much of methodologies that we spend learning about and adopting can easily be translated to these other areas of our lives.

So as I brace myself for 2009, I find myself asking, How can I lead a more Agile life?

I’d love to hear how you’re adopting best-practices inspired by Agile methodologies in your life and I promise to share mine over the coming year.

  • [Agile development begins
within...](http://www.robbyonrails.com/articles/2006/04/21/agile-development-begins-within)
```text
-   [Agile development begins within...
```text
continued](http://www.robbyonrails.com/articles/2006/04/26/agile-development-begins-within-continued)
```text
-   [Those that Tend the Store need
```text
Dialogue](http://www.robbyonrails.com/articles/2007/01/04/those-that-tend-the-store-need-dialogue)

Rails 3 and Merb

December 23, 2008

So… Rails and Merb are going to be merged into Rails 3. (link)

Has hell frozen over?

[(it has in Portland the last week)]{.small}

I’m curious about how the revised core team will incorporate the library-agnostic view points into Rails without increasing the complexity for configuration. For example, being able to use a different ORM is great, but at the same time, one of the things that I have really liked about Ruby on Rails was that it did make decisions ahead of time for you. Conventions over Configuration and all that jazz. While they intend to keep these defaults, I really wonder how much more configuration will be involved. Be that as it may, Rails and Merb are run by some of the best developers I’ve ever known… so I am sure these decisions will not be made without some deep consideration.

Rails application don’t all look and smell the same, but it’s nice to know that there is consistency across all of our client applications. What I’m concerned about (from an efficiency standpoint) is that this could lead to project-diversity at the cost of experimenting. Pre-Rails, the development teams that I was a part of was constantly trying out new libraries from client project to project, but this came at a huge cost. We weren’t able to leverage our experience with previous projects like our team does with Ruby on Rails currently. (hell, I even helped write two different ORMs in the two years before Rails for PHP… and still wasn’t satisfied)

But, this isn’t so much a technical problem as much as a people problem. The thing is… is that Rails helped solve a people problem with a technical answer. Having testing, consistency, and other best practices built-in did the world a huge favor. …and all it took was someone like DHH to throw his opinion out there and stick to it. It took me nearly a full year to really embrace a lot of these conventions, but in the end.. it paid off.

While I do feel that it’s in developers best interests to try out new approaches, I just don’t think it should be on your clients dime. This was part of the reason why I quit my last job to start Planet Argon full-time. I really wanted to get away from that cycle.

Since we (Planet Argon) adopted Ruby on Rails four years ago, we’ve been able to build off of every project we had worked on before. We since adopted things like RSpec and JQuery, but our team decided on these changes after someone took the initiative to experiment with these on internal and personal projects. Having this foundation has freed up a lot of our time to focus on other issues as a team, like Interaction Design, Usability, and client collaboration.

As far as Merb itself, I honestly haven’t tried to do anything with it since about 0.2/0.3. I gave up quickly though because the documentation didn’t help me get anywhere and my time is valuable. I’ve since seen that documentation has improved drastically, but I haven’t been able to prioritize the time needed to really play with it. With Merb being merged into Rails 3, it means that I really should spend more time exploring it as we might be able to leverage some of it’s benefits without as much of an investment.

Much of the lack of great interest in Merb was because I felt Rails had consistently provided our team with a solid foundation for a majority of our internal and client applications. The old saying, “if it ain’t broke, don’t fix it.” Not to say that others haven’t expressed a lot of excitement about Merb and it’s benefits, I just didn’t see there being enough of a productivity gain to warrant the time investment required to really learn and use a new framework… and the one thing that I have had trouble with was that it didn’t sound like Merb encouraged a default set of libraries. I could be totally wrong, but that’s been the perception I’ve had based on how it was branded.

But… the best part about this for you, me, and the Rails community? Is that I don’t need to register robbyonmerb.com anytime soon. ;-)

I hope that you’re all having a great end to 2008 and am excited to see all the energy in the Ruby/Rails/Merb community. I suspect that between these two (now-merged) teams, we’ll have an even better platform to develop web applications on. I believe this is great news and I’m all in favor of seeing the Ruby community conquer these challenges that lay ahead.

Anyhow, I’m just thinking out loud. What are your thoughts?

RailsBoxcar.com 2.0

December 17, 2008

In case you missed the tweet from Alex …

::: thumbnail Twitterrific :::

Our team just designed, developed, and deployed a new site for, Boxcar, our streamlined deployment environment for Ruby on Rails applications.

::: thumbnail Boxcar :::

Feel free to take a tour to learn more about our product plans, which currently start as low as $59/month.

If you have a project that you’ll be launching in the coming months, get in touch with us. :-)

Launching Ruby on Rails projects, a checklist

December 14, 2008

::: warning Since publishing this article, I have given a talk on this topic at Rails Underground 2009. I invite you to checkout the slides. :::

As mentioned in a recent post, I’m hoping to share some lessons that were learned throughout the process of launching a client project. Over the past few years, we’ve been part of several dozen client projects and the big launch date is always an anxiety-filled, yet exciting point for the client and our team. I wanted to provide a quick list of a few the things that our team considers vital before launching that next big project. While most of these things might seem obvious, it’s still good to cover the basics and I hope a few people find it helpful.

Hosting

Our company has been offering Ruby on Rails hosting for nearly four years and a few years longer with the PHP5 and PostgreSQL world. Given that, we’ve seen customers come to us at the last minute before they launch and wanting to get things setup and deployed right away. Quite often, this is their first experience deploying a Ruby on Rails application and there has historically been a semi-steep learning curve to do this. It’s really encouraged that you get this stuff figured out ahead of time. If you’re lucky, some hosting companies might offer cheaper plans so that you can begin to get things setup a few months or ahead of time and upgrade your plan prior to the big launch. This is how our Rails Boxcar hosting plans work.

We’ve seen a lot of customers avoid engaging with a hosting company more than a week or two before their launch because they want to reduce their monthly expenses, but the reality is that if you end up saving yourself a few hours of work by not scrambling at the last minute to get things setup, the hosting costs will pay for themselves. Several of our customers have learned this the hard way and as a result, this has resulted in extra stress that might have been avoidable if things had been ready earlier on.

The basic process that our team is to get a real deployment environment setup as early in the design and development process as possible. Often times, this will be 4-6 months before launch on larger projects. In our process, we aim to have a staging environment that mirrors our production environment. We tend to use a Boxcar Lite plan for our own client projects and get the deployment process working and automated. When it’s time to launch, we can easily upgrade the Boxcars with more resources to one or more Plus plans.

If you’re in the market for a hosting company, do keep us in mind, but if we can offer any advice, be sure to find out how you can scale upwards to meet your initial 3-6 month growth targets. Don’t worry about planning too far ahead in the future, until you see how traffic picks up and how the application and databases perform, you’ll be spending a lot of time guessing without data. If you’re new to this and aren’t sure, I’d encourage you to speak with a Ruby on Rails deployment specialist.

A few things to consider here:

setup early. Make sure everything works and set it up to work with
multiple deployment environments. (staging, production, etc.)
-   Use [Boxcar
    Conductor](http://www.robbyonrails.com/articles/2008/04/15/boxcar-conductor-rails-deployment-made-easy)
    with your Rails Boxcar. ([Boxcar Conductor on
    github](http://github.com/planetargon/boxcar-conductor/tree/master))
```text
-   Use the **HTTP Basic Authentication**, which is available in Ruby on
```yaml
Rails to keep peeping toms (competitors, search crawlers, spammers,
etc.. ) out of your project while you're deploying to your staging
environment. We tend to give out a `.htaccess` user/pass with this
method to the stakeholders so they can access the site whenver they
need to.
-   Rails documentation on HTTP Basic Authentication: [view
    docs](http://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Basic/ControllerMethods.html)
-   Watch a Railscast for using HTTP Basic Authentication: [watch
    screencast](http://railscasts.com/episodes/82)
```text
-   Get your automated tasks (cron jobs) setup way before launch. Verify
```yaml
that things are working here at the right times
-   Extra-credit: Check server time settings to make sure you're not
    running big tasks at time periods when heavy traffic is expected
```text
-   Make sure your hosting provider has monitoring setup. It's good to
```yaml
gauge uptime % from launch
-   Extra-credit: Setup your own monitoring with
    [Pingdom](http://pingdom.com/) or similar service to make sure
    you know when things are down. (You can audit your hosting
    provider this way!)
```ruby
There are a handful of really great hosting companies out there for Ruby
on Rails. Be sure to do your homework early! This isn't something you
want to do at the last minute.

Reminder: **Keep your project releasable at all times.**

## Search Engines and Analytics

Before the big launch, be sure that you have outlined a consistent
pattern for managing the HTML page titles on each page. Getting targeted
traffic to your new web application is (usually) vital. Our team has
adopted a basic pattern that we use throughout the application. This way
we don't have to go through at the last minute and figure out where
titles are and/or aren't being set.

In a previous post, I [shared a basic
plugin](http://www.robbyonrails.com/articles/2008/03/26/managing-seo-friendly-html-titles-with-rails)
that our team uses on projects to manage page titles on a view-by-view
basis.

Additionally, be sure to take advantage of using descriptive permalink
URLs.

Another tip is to setup your application with analytics ([google
analytics](http://google.com/analytics) is free!) If there is one thing
that I wish we had setup from day one on every project in the past, was
a set of conversion goals. So, be sure to get into your analytics
account and prepare your application so that you can track these goals
from the moment your application is launched. Collecting as much data
about your visitor's usage habits is going to help you in the coming
weeks and months as you tune things based off of feedback and this data.
Also, after you begin to introduce changes, you can analyze these
metrics to verify that you're improving things and not the opposite.

So, be sure that you are doing the following:

-   Have implemented descriptive page titles and urls
-   Are ready to track your site visitor's usage habits from the
```yaml
starting gate
-   Conversion goals for obvious things like:
    sign-ups/registrations, viewing your product tour, contact
    requests, etc.
```ruby
## When Things Go Wrong / Tracking Exceptions

What happens when things go wrong? We've been amazed by how many
projects we've seen have been in production for months/years and lacking
something that seemed so obvious. Exception notifications! All too
often, we've seen teams totally unaware that things were failing for
their customers and not being reported to anybody. The easiest way to
track exceptions in the past was to use the
[exception_notification](http://github.com/rails/exception_notification/tree/master)
plugin that the Rails team manages. You can have this plugin send your
development team emails with a backtrace and all the goodies that'd
normally show up in a 500 error. At a minimum, you should be using
something like this.

-   Tip: Make sure your hosting environment can send out emails!
```text
(otherwise, you'll never know about these problems...eek!)
```ruby
However, in the last year, the Rails community has seen two options,
[Exceptional](http://getexceptional.com/) and
[Hoptoad](http://www.hoptoadapp.com/) introduced for managing
exceptions. Our team has only used Exceptional so far, because our good
friends at [Contrast](http://www.contrast.ie/) invited us to be early
beta-testers for their new service. We love the Exceptional's
integration with Lighthouse, which is the bug/issue tracking application
that we're currently using. With Exceptional, our team is able to search
through and track exceptions in our application and have a good meter on
the overall health of our application. This solution works so much than
the email-based approach because we can track which exceptions have been
opened and sent to Lighthouse and if they've been closed by someone
already.

I've heard great things about Hoptoad as well, but have yet to test it
out. Would be interested to read a comparison between the two and am
curious if there are other services for this currently.

## Non-default 404 and 500 pages

Honestly, this is one of those things that we tend to forget about until
the last minute. When you're launching a new project, you're bound to
have a bug and/or a few broken links not accounted for. What you want to
avoid is having your customers end up on an unhelpful page that looks
like this:

::: thumbnail
[![The page you were looking for doesn\'t exist
(404)](http://img.skitch.com/20081215-q11ckmua6qe5gf4nsd6ghptw83.preview.jpg)](http://skitch.com/robbyrussell/6txe/the-page-you-were-looking-for-doesn-t-exist-404)
:::

It doesn't take too long to put something together that is a bit more
helpful for your visitors.

::: thumbnail
[![AlphaClone --- Page not
found](http://img.skitch.com/20081215-12prkpg4b98rptwiwy637ss1.preview.jpg)](http://skitch.com/robbyrussell/6txm/alphaclone-page-not-found)
:::

So, do yourself a favor and add a ticket for your designers to design a
custom 404 and 500 pages to replace the defaults that are provided by
Ruby on Rails in `public/`.

## Hold your client's hands

If you're working with startups, do remember that this is quite possibly
their first launch. It's important to remember that they're going to be
going through their own spectrum of feelings and it's our job to help
get them through the process with an eased mind. Show them that you have
things covered, that things are ready to go, alert them when things pop
up... in a nutshell. Keep them informed about the challenges and do what
you can help to manage their stress. If they've just contracted you for
an extended period of time to help get their **big idea** designed and
developed, remember that this launch is just the beginning of the race
for them. They have a big journey ahead of them and you just helped them
get their new car engine built. Make sure they know that things are
likely to breakdown along the way, need to be refueled (refactor!
refactor!), and need service repairs. The worst thing you can do is set
the expectation that nothing will go wrong once their application is
released into the wild. They need to budget for this early on so that
they can pace themselves after launch. (this is a big topic definitely
worth of it's own post)

Just remember that this should be a big celebration for your team and
client. Remember to celebrate! (and then follow it with a retrospective)

## In Conclusion

As mentioned, these are just a handful of things that we have learned to
avoid overlooking (through trial and error). I'm hoping to share more
thoughts on launching in the near future and would love to hear from all
of you on things that you've come across. What works? What doesn't work?

What is on your checklist for launching successful projects?

### Related Articles

-   [The Art of Delivery, part
```text
2](http://www.robbyonrails.com/articles/2008/05/22/the-art-of-delivery-part-2)
```text
-   [Agile development begins
```text
within...](http://www.robbyonrails.com/articles/2006/04/21/agile-development-begins-within)
```ruby
-   [Audit Your Rails Development
```text
Team](http://www.robbyonrails.com/articles/2007/06/17/audit-your-rails-development-team)
```text
-   [Embracing Chaos, part
```text
1](http://www.robbyonrails.com/articles/2007/12/17/embracing-chaos-part-1)

AlphaClone on PostgreSQL and Ruby on Rails

December 12, 2008

::: {.thumbnail style=”float:right;”} tour-ss-full-berkshire.jpg (JPEG Image, 370x713
pixels) :::

Earlier this week, our team launched a client’s project into the public. We began working on it early this year and it was quite an endeavor for our team. The company that we helped launch is AlphaClone, a premier stock research and portfolio simulation service for individuals and professional investors alike. Clone, backtest and track over 230 top fund manager portfolios. More than 15,000 pre-generated clones and nearly limitless possibilities based on your own custom groups of funds. Take a tour of AlphaClone…

It’s hard to deny that I’m insanely proud of the team at Planet Argon for bringing our client’s business idea to reality. We’ve been enjoying keeping up on how the press is responding so far since they’ve launched. I expect that they’ll do well with their business endeavor and look forward to helping them evolve and expand.

I’ve been asked to share some stories and lessons learned throughout the project. Given that we tackled a lot on the Interaction Design side of things in addition to relying a lot more on some of the advanced features of PostgreSQL (we’re dealing with a TON of data here), we have things to share. So, stay tuned as I’ll be highlighting some of those lessons over the coming week(s).

Additionally, if you’re looking for a team to help you execute your next big idea, give us a call!

Lighthouse tickets and Git branching

December 11, 2008

We’re currently using Lighthouse as our ticketing system with clients for maintenance/bug requests. We’re also using Github for all of our major client projects. I’m sure that many of you take advantage of the Lighthouse service that Github allows you to use so that your commits can trigger actions on your tickets in Lighthouse.

If you’re not already, you might consider running (cheat ?):

  • cheat lighthouse
<!-- -->

lighthouse:

  • Commit comment [#213] Adds message as comment to ticket #213 ```

The HTTParty has just begun

November 26, 2008

After releasing the new RubyURL API, I decided that it was time to look around at libraries to interact with it. I came across a new Ruby gem from John Nunemaker named, HTTParty, which aims to make it easy to talk to XML and JSON-based web services. Be sure to read John’s announcement of HTTParty.

So, I decided it might be fun to introduce more people to the gem by showing you all how to use it to talk to the new RubyURL API.

Install HTTParty

Before we get started, you’ll need to install the HTTParty gem with the following command:

   ~ : sudo gem install httparty
  Password:
  When you HTTParty, you must party hard!
  Successfully installed httparty-0.1.6
  1 gem installed
  Installing ri documentation for httparty-0.1.6...
  Installing RDoc documentation for httparty-0.1.6...
```shell
Great! Now that **we're ready to party hard**, let's build something.

## Talking to the RubyURL API

The [RubyURL API](http://rubyurl.com/api) currently supports both XML
and JSON, which are each supported by HTTParty. The great thing about
HTTParty is that all you need to do is include it in a class and you're
able to quickly talk to remote services.

In this following example, we're going to create a new class called
`Rubyurl`.

````ruby
class Rubyurl
end
````ruby
What we'll want to do now is include the HTTParty library. (**note:**
you'll need to require both rubygems and httparty gems and I'll skip
those lines in following code samples)

````ruby
class Rubyurl
  include HTTParty
end
```text
The HTTParty provides [a few class
methods](http://github.com/jnunemaker/httparty/tree/master/lib/httparty.rb),
which we can use to configure our library. We'll go ahead and specify
the `base_uri`, which we'll set to `rubyurl.com`.

````ruby
class Rubyurl
  include HTTParty
  base_uri 'rubyurl.com'
end
```bash
Now that our class is setup to talk to the
[Rubyurl.com](http://rubyurl.com) site, we'll want to add a new method
which we can use to communicate with the RubyURL API. We'll call this
`shorten` as we're using RubyURL to shorten long URLs... right?

````ruby
class Rubyurl
  include HTTParty
  base_uri 'localhost:3000'

  def self.shorten(website_url)
  end
end
```yaml
Our new `shorten` method will expect us to provide it with a website
url, which we'll want RubyURL to return a shortened URL for. The PATH
for the API that we'll want to talk to is: `/api/links`, which we're
expected to pass XML or JSON to.

Here are two examples of using the RubyURL API with HTTParty.

### RubyURL via JSON w/HTTParty

We're going to use the `post` method that is provided with HTTParty to
send a request to `/api/links.json`. As you can see, we're providing the
original website url to the web service.

````ruby
class Rubyurl
  include HTTParty
  base_uri 'rubyurl.com'

  def self.shorten(website_url)

```javascript
post('/api/links.json', :query => { :link => { :website_url => website_url } })
```text
end
end
```yaml
When ran, it'll produce the following:

````ruby
>> Rubyurl.shorten('http://github.com/jnunemaker/httparty/tree/master/lib/httparty.rb').inspect
=> {"link"=>{"permalink"=>"http://rubyurl.com/uJVu", "website_url"=>"http://github.com/jnunemaker/httparty/tree/master/lib/httparty.rb"}}
```shell
Pretty simple, eh?

### RubyURL via XML w/HTTParty

The great thing about HTTParty is that you can use XML without changing
much.

````ruby
class Rubyurl
  include HTTParty
  base_uri 'rubyurl.com'

  def self.shorten(website_url)

```javascript
post('/api/links.xml', :query => { :link => { :website_url => website_url } })
```text
end
end
```text
Produces the following

```ruby
http://github.com/jnunemaker/httparty/tree/master/lib/httparty.rb
http://rubyurl.com/uJVu

Closing thoughts

So… there you have it. HTTParty makes it extremely easy to interact with various web services that work over HTTP. I’d encourage you all to take a few minutes to experiment with it and see what crazy ideas that come to mind during the process. :-)

Lesson Learned: Git Ref Naming

September 18, 2008

Our team has been working our way into the Git world. One of our big client projects is now 100% git while the other is still on Subversion for another month or so. (I’m getting by with git-svn, the gateway drug on that). We’ve had pretty much nothing but success with Git for quite some time, but recently this repository started to get chaotic, which has eaten up time… which isn’t conducive to productivity.

So, I wanted to share a quick lesson that we learned today after scratching our head for a while. It’s important that you avoid having a branch on a remote repository that shares the name of a tag in your local and/or remote repository.

I REPEAT.

It’s bad mojo to have a tag and branch share the same name. Things that you’d expect to just work… don’t. This was causing us to see warnings and errors like the following, which we weren’t really sure what to make of it.

“warning: refname ‘staging’ is ambiguous.

“error: src refspec staging matches more than one.”

This started about two weeks ago when we started a few new remote branches: staging and design. It seemed to be going okay but we managed to muck up things when we merged those two together and some of us were having success fetching/pulling/pushing to staging and others were having to specify :heads/staging and couldn’t have a local branch named staging. Needless to say, it was causing some problems and slowing us down.

This afternoon, we finally noticed in the GitHub interface that there was a tag named staging. Hmm… interesting. We verified this by using git show-ref.