Read my latest article: 8 things I look for in a Ruby on Rails app (posted Thu, 06 Jul 2017 16:59:00 GMT)

Switch to Passenger (mod_rails) in development on OSX in less than 7 minutes or your money back!

Posted by Wed, 11 Feb 2009 21:52:00 GMT

We recently switched our default builds of Rails Boxcar to leverage the benefits of using Passenger (mod_rails) for deployment of your Ruby on Rails applications and it’s been working out great for our customers. Several of our customers and colleagues mentioned that they also began using Passenger in development, which was intriguing.

But… Mongrel has been working great for us for the past few years. Why switch?

It’s true, I’ve been happily using mongrel since it came out as a replacement to webrick back in early 2006, which makes it about 28 in dog years.

Nigel and I
Nigel and I.. 2 1/2 years ago back when Mongrel was just a puppy

But… over the next few weeks, I’m going to evaluate Passenger in my development workflow. There’s no better way to try something then to jump head first. So… here goes.

locke
this guy was a passenger…and I recently started to watch the show

Our team will be evaluating Passenger in our development work flow with a forthcoming blog post but if you want to get your feet wet right away, here are some instructions for setting up Passenger on OSX with PrefPane, which were inspired by Manfred’s posts.

Installing Passenger via RubyGems

To install Passenger on your OSX machine, just run the following with root credentials.

sudo gem install passenger

This will install the passenger gem on your machine. Now we need to go ahead and run a script that is provided with this gem (also with root credentials).

sudo passenger-install-apache2-module

You’ll want to follow the instructions that appear. When you see something similar to the following output from the command, you’ll want to copy/paste that into an apache configuration file. I just created a file at /etc/apache2/other/passenger.conf.

Edit this file with your editor of choice

mate /etc/apache2/other/passenger.conf

Mine looks like:


  #/etc/apache2/other/passenger.conf

  # Passenger modules and configuration
  LoadModule passenger_module /opt/local/lib/ruby/gems/1.8/gems/passenger-2.0.6/ext/apache2/mod_passenger.so
  PassengerRoot /opt/local/lib/ruby/gems/1.8/gems/passenger-2.0.6
  PassengerRuby /opt/local/bin/ruby

  # Set the default environment to development
  RailsEnv development

  # Which directory do you want Apache to be able to look into for projects?
  <Directory "/Users/robbyrussell/Projects/development">
      Order allow,deny
      Allow from all
  </Directory>

Once you finish running through sudo passenger-install-apache2-module, you’ll need to restart Apache on your workstation. This can be done by simply turning off/on Web Sharing in your Sharing Preference Pane.

Sharing

Alright, we got through the hard part. Now, in order for you to begin using Passenger, we need to setup Apache to point to your individual Ruby on Rails application(s). You can hack on Apache configuration files more, but there is an easier way thanks to the Passenger Preference Pane.

This will manage your VHost files for you!

Setting up Preference Pane

If you followed my post on installing Ruby on Rails via MacPorts, you’re going to need to install Ruby Cocoa, which can be done with the following. If you’re using the Ruby provided from Apple, you can skip this step.

sudo port install rb-cocoa

Once that is done, go ahead and move on and download Passenger Preference Pane. Once downloaded, you can install the preference pane, by double-clicking on the following file.

PassengerPane-1.2

The next part is really simple as well. Just begin to add your various Ruby on Rails projects into the Preference Pane… and when you’re done, you should be able to run your applications over port 80 without any problems.

As you can see, I’ve already setup a handful of projects and we don’t have to start/stop mongrels for each one or worry about port numbers when running multiple projects. (time savings!)

Passenger

Voila. Simple enough. You might need to stop/start Apache, couldn’t remember if I needed to or not.

For each host that you add into this panel, it’ll automatically be added so that you can immediately browse to http://yourhost.local and it should just work. :-)

Things to still figure out…

Debugging. If you’re used to doing --debugger, it appears that you can do something similar with the socket-debugger plugin. Not tried it myself, but worth looking into.

Browser testing via VMWare/Parallels/VirtualBox. Does anybody have any tips on how to best appraoch this? Our designers are curious…

As I mentioned, this is day one of trying it out and managed to motivate our entire design and development team to try it with me so that we can all learn about issues together and find solutions quicker. If you’ve been using this approach for a while, I’d be interested in hearing your story and if there are any issues that we should be aware of.

Get to know a gem: Ghost

Posted by Mon, 12 Jan 2009 05:18:00 GMT

In my last post, Subdomain accounts with Ruby on Rails explaind, I mentioned that you’d need to modify your /etc/hosts file to use custom subdomains for development/testing. Apparently, there is a much better way to handle this that I was introduced to by Nathan de Vries. Nathan suggests using a gem that I hadn’t heard of before that bares the name of Ghost (view project on github).

Ghost describes itself as…

“A gem that allows you to create, list, and modify local hostnames in 10.5 with ease…”—

If you’ve ever had to modify your /etc/hosts file for anything local, I highly encourage you to check out this shiny gem.

Installing Ghost

Like most gems, you can just install Ghost with the following command.


~ : sudo gem install ghost
Password:
Successfully installed ghost-0.1.2-universal-darwin-9
1 gem installed
Installing ri documentation for ghost-0.1.2-universal-darwin-9...
Installing RDoc documentation for ghost-0.1.2-universal-darwin-9...

Okay, now that Ghost is installed, let’s see what we can do with it.

Using Ghost for local domains/subdomains

Ghost is fairly straight forward. It’s essentially a friendly wrapper for dscl, which is the Directory Service command line utility for Mac OS X. I’ve never played with that directly, but it seems that with Ghost… I shouldn’t need to. :-)

With Ghost, you can add, modify, and delete entries in the Directory Service by issuing any of the following commands. Let’s start out by running ghost to see what we have here.


 ~ : ghost
USAGE: ghost add <hostname> [<ip=127.0.1.1>]
       ghost modify <hostname> <ip>
       ghost delete <hostname>
       ghost list
       ghost empty

Okay, let’s see if there is anything already listed.


   ~ : ghost list
  Listing 0 host(s):

Nope. Let’s test this out. First, we’ll try to ping a domain name that we hope doesn’t exist.


   ~ : ping bigbrown.cow
  ping: cannot resolve bigbrown.cow: Unknown host  

Alright, now we’ll add bigbrown.cow with ghost.


   ~ : ghost add bigbrown.cow
  Password:
    [Adding] bigbrown.cow -> 127.0.0.1

As you can see, it required root credentials to do this as it’s system-wide. Let’s now see if we can talk to bigbrown.cow.


   ~ : ping bigbrown.cow     
  PING bigbrown.cow (127.0.0.1): 56 data bytes
  64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.047 ms
  64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.035 ms
  ^C
  --- bigbrown.cow ping statistics ---
  2 packets transmitted, 2 packets received, 0% packet loss
  round-trip min/avg/max/stddev = 0.035/0.041/0.047/0.006 ms

Excellent! If we run ghost list again, we should see this record.


~ : ghost list
Listing 1 host(s):
  bigbrown.cow -> 127.0.0.1

We can modify the record to a non-localhost IP as well with ghost modify.


   ~ : ghost modify bigbrown.cow 192.168.10.104
    [Modifying] bigbrown.cow -> 192.168.10.104
   ~ : ghost list
  Listing 1 host(s):
    bigbrown.cow -> 192.168.10.104  

I’ll let you play with it yourself as there isn’t much to it. This is a great little addition to my development environment. Thanks to Nathan for pointing it out and to Bodaniel Jeanes for creating this useful gem.

Subdomain accounts with Ruby on Rails explained

Posted by Sun, 11 Jan 2009 22:30:00 GMT

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 
       create  app/models/
       create  test/unit/
       create  test/fixtures/
       create  app/models/account.rb
       create  test/unit/account_test.rb
       create  test/fixtures/accounts.yml
       exists  db/migrate
       create  db/migrate/20090111220627_create_accounts.rb

Great, let’s migrate our application.

   account-demo : rake db:migrate
  ==  CreateAccounts: migrating =================================================
  -- create_table(:accounts)
     -> 0.0045s
  ==  CreateAccounts: migrated (0.0052s) ========================================

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
     exists  db/migrate
     create  db/migrate/20090111221009_add_index_to_account_subdomain.rb

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
  ==  AddIndexToAccountSubdomain: migrating =====================================
  -- add_index(:accounts, :subdomain, {:unique=>true})
     -> 0.0047s
  ==  AddIndexToAccountSubdomain: migrated (0.0050s) ============================  

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
  end  

..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 <strong>{{value}}</strong> is reserved and unavailable."

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]

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
  # ...
  before_filter :login_required

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 yeah, I’ve been reading more Seth Godin recently…

Launching Ruby on Rails projects, a checklist

Posted by Mon, 15 Dec 2008 00:28:00 GMT

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:

  • Get your Capistrano or Vlad deployment tasks setup early. Make sure everything works and set it up to work with multiple deployment environments. (staging, production, etc.)
  • Use the HTTP Basic Authentication, which is available in Ruby on 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
    • Watch a Railscast for using HTTP Basic Authentication: watch screencast
  • Get your automated tasks (cron jobs) setup way before launch. Verify 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
  • Make sure your hosting provider has monitoring setup. It’s good to gauge uptime % from launch
    • Extra-credit: Setup your own monitoring with Pingdom or similar service to make sure you know when things are down. (You can audit your hosting provider this way!)

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 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 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 starting gate
    • Conversion goals for obvious things like: sign-ups/registrations, viewing your product tour, contact requests, etc.

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 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! (otherwise, you’ll never know about these problems…eek!)

However, in the last year, the Rails community has seen two options, Exceptional and Hoptoad introduced for managing exceptions. Our team has only used Exceptional so far, because our good friends at Contrast 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:

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.

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

AlphaClone on PostgreSQL and Ruby on Rails

Posted by Fri, 12 Dec 2008 13:23:00 GMT

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

Posted by Thu, 11 Dec 2008 16:36:00 GMT

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

    * tagged - adds tag to the ticket (does not replace)
    * responsible - sets the user responsible for ticket (responsible:none to
    clear)
    * milestone - sets the milestone for ticket (milestone:none to clear)
    * state - sets state (new, open, hold, resolved, invalid)

  - Commit comment [#213 tagged:committed responsible:johan milestone:"Launch" 
  state:resolved]

With your commit messages, you can just pass in the ticket # and resolve your ticket without needing to interact with Lighthouse too much.

Okay, so one of the problems that I’ve had with this process is that I have had to constantly look back in my browser to see what the ticket # was that I was working on. So, I decided to start writing it down on a notepad as I was working through tickets so that I could look down at my desk, but this wasn’t terribly efficient either.

So, I decided to start leveraging the features of git to help me out. For each ticket that I work on, this is my process.

In Lighthouse, I decide which ticket I’m going to work on next. I then create a local branch using the ticket # in the name. Example: LH_1623

The workflow ends up looking like:

alphaclone git:(master): git checkout -b LH_1615

alphaclone git:(LH_1615): <—I am using zsh and have it display the current local branch

I then work on this ticket. Since I’m working within the branch and my prompt reminds me what ticket # is being worked on, it makes it easy for me to add this into my commit message.

git commit -m "Fixed the do-whacky issue with data importing. [#1615 state:resolved]"

At some point, this will be ready to be merged back into master and pushed to Github.

git checkout master

git merge LH_1615

git push origin master

Github will take your commit message and pass it over to Lighthouse and your ticket will be marked as resolved automatically. This workflow has saved me a lot of time from navigating through Lighthouse and has also helped me stay focused on individual tickets throughout the day. Quite often, I’ll get interrupted by something non-development related and seeing the ticket # in my terminal helps get me back on task.

I’ve managed to encourage a few of the others at Planet Argon to adopt this ticket-based branch process as well so that when we need to collaborate on a ticket we publish the ticket branch to Github so that others can work on it as well. (happens a lot when a designer and developer need to work together on the same issue/feature)

Anyhow, just a quick little introduction to something simple that I did that has definitely helped me become a little more efficient throughout the day. Perhaps you have a better approach and/or tips for others that you’d like to share?

Related Posts

Older posts: 1 2 3 4 5 6 ... 13