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

Building a prototype? Bring some rope.

Posted by Thu, 09 Apr 2009 19:57:00 GMT

While scanning through Allison’s copy of Designing for the Digital Age: How to Create Human-Centered Products and Services, I came across this nugget.

The problem with software prototypes

It seems to be widely understood that industrial design and mechanical engineering prototypes—from paperclips and tape to polished appearance models—are disposable learning tools. Prototyping is clearly distinct from manufacturing, so it would be ludicrous to think that even a late-stage prototype could be reused as part of the final product. In software, however, the tools used for anything other than paper prototyping are generally the same tools used for “manufacturing” (i.e., writing production code). For this reason, many stakeholders can’t see why a detailed prototype that appears functional is still many months away from completion.

It immediately reminded me of a few posts that I had written about three years ago on the topic of developing prototypes and NOT keeping them.

The author continues with…

It’s important to educate stakeholders that prototype code is kind of like the illusion of automatic doors on Star Trek—it looks like it’s working, but it’s really a guy standing behind the wall pulling a rope.

I completely agree that education is the most important aspect to managing client expectations. With regard to the amount of work that you put into a prototype, we need to be careful on how much time and energy is put into them. If we can get away with a guy (or some quick Javascript hacks) to demonstrate possible functionality, make sure we aren’t using much more than rope. Rope is cheap. Prototypes should be too.

Related Posts

Lessons through failure. Episode 1

Posted by Sat, 17 Jan 2009 22:34:00 GMT

I fucked up this last week.

On Monday, our primary contact for a large client sent over some last minute requirements and deadlines that were needed by end-of-day Wednesday. I didn’t have a lot of time to collect requirements and execute it without having to rearrange my priorities. But, I accepted the challenge.

The big change involved was that we were going to be supplied with a ton of data to be imported in to the database and approximately 20% of the data provided was new records, while the rest were duplicates. However, the other 80% wasn’t to be discarded as there were a few attributes that needed to be updated from the data file (which was supplied from the client’s parent company). In my haste to get the task done on time (didn’t get proper export file to be imported in our system until Wednesday morning)... I ended up running a few tests locally and pushed it out to production.

I managed to get the import file to run in production before leaving on Wednesday afternoon. The following morning, I came into the office to find out that my import process didn’t match up records properly and resulted in nearly all of the 80% side of that to be duplicated in the system. This resulted in lost productivity for our client, their vendors, and our team over a 12 hour period as people were confused about why reports were running weird, online transactions didn’t account for the duplicated, etc.

It took me most of Thursday and Friday to clean up the data that got skewed due to that oversight. Hi ho.

So, the take away from this? Sure, I could have blamed it on a lack of sufficient time to properly test things, but that’s bullshit. I should have had at least one other developer from our team review the problem and evaluate my proposed solution prior to me attempting to push into production.

Luckily, the client was happy that we were able to finish the last minute tasks, despite the unexpected headaches that cropped up.

If anything, I was just disappointed in myself, but Alex reminded me how important it was to fail early, fail often. It didn’t kill me (or anybody else for that matter), cost us the project, nor was it irreparable.

In the real world, deadlines and requirements change on a moments notice and it’s experiences like this that will make ourselves more confident that we can quickly respond to and execute.

What was your latest failure?

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…

ShortURL 0.8.4 released and gets a new mainainer... me!

Posted by Sun, 06 Jan 2008 23:49:00 GMT

Earlier today, Vincent Foley was kind enough to hand over maitenance of the the ShortURL project on RubyForge to me. He first released it back in 2005, which I blogged about as RubyURL was the first shortening service that it supported (and is the default). Unfortunately, the release of RubyURL 2.0 broke backwards compatibility and Vincent wasn’t maintaining it anymore. So, earlier, I decided to patch this and got a new version released that now works with the current RubyURL site.

While working on the code, I decided to extend the compatible services to include moourl and urlTea.

These updates are available in ShortURL version 0.8.4.

Install the ShortURL gem

Installation is a snap… (like 99.7% of rubygems…)


  ~ > sudo gem install shorturl                                                                                                                                                                                                           Password:

  Successfully installed shorturl-0.8.4
  1 gem installed
  Installing ri documentation for shorturl-0.8.4...
  Installing RDoc documentation for shorturl-0.8.4.  

Using ShortURL

The ShortURL gem provides the ShortURL library, which you can use from any Ruby application.

Using the ShortURL library


  ~ > irb                                                                                                                                                                                                                           
  irb(main):001:0> require 'rubygems'
  => true
  irb(main):002:0> require 'shorturl'
  => true
  irb(main):003:0> ShortURL.shorten( 'http://www.istwitterdown.com' )
  => "http://rubyurl.com/P9w" 

As you can see…it’s really straight forward.

Let’s try it with a few other services.


irb(main):004:0> ShortURL.shorten( 'http://www.istwitterdown.com', :moourl )
=> "http://moourl.com/fvoky" 
irb(main):005:0> ShortURL.shorten( 'http://www.istwitterdown.com', :tinyurl )
=> "http://tinyurl.com/2t3qmh" 

Using the shorturl command-line tool

Many people don’t know that ShortURL provides a command-line tool, which you can use after installing the gem.


  ~ > shorturl http://istwitterdown.com                                                                                                                                                                                               
  http://rubyurl.com/Lwk

If you’d like to see more services provided than the ones listed here, please submit feature requests and/or patches on the rubyforge project.

ShortURL Documentation

To see the latest documentation for the project, please visit:

My favorite part about this? My rbot plugin for RubyURL works again!

rbot and rubyurl
Uploaded with plasq’s Skitch!

Happy URL-shortening!

Advanced Mathematics and Programming

Posted by Tue, 01 Jan 2008 19:40:00 GMT

First of all, Happy New Year!

The other day I received an email from a friend where she asked me if I thought that having excellent math skills were important in a programmers career. I’ve heard this question asked before and while I thought that might have been the case when I was a lot younger (when I had zero plans to go into the IT world)... I’ve not seen this to be true. My response to her was that it really depended on the types of programming work that one might want to go into. There are definitely programming jobs that require extremely advanced mathematical skills, but I’d guess that many, if not most, don’t really have that sort of prerequisite.

So, as I was saying. I think it really depends. It depends on what sort of programming you’re interested in pursuing. In general, when we’re looking to hire someone at Planet Argon, we’re looking for people with good research and problem solving skills. Programming languages are tools to help solve problems and build things. So, while math skills are useful, they aren’t likely going to make or break a developer.

Like any career, it should be something that you’re passionate about.

I’m curious. As programmers… how would you respond to the following question?

“Should an advanced knowledge of mathematics be a prerequisite in pursuing a career in programming?”

I can only answer the question from my own perspective and would like to share some others. Thanks!

PostgreSQL: An elephant wearing a hula skirt and I find it sexy

Posted by Thu, 20 Apr 2006 22:30:00 GMT

9 comments Latest by Joe Wed, 26 Apr 2006 09:01:52 GMT

Last week, I gave a live presentation to ~250 people, which was basically me walking through the process of using Ruby on Rails to talk to a legacy database1. For my example, I used the Dell DVD database... the PostgreSQL version. You can review some comments about my presentation by reviewing this entry on the blog of Ryan Davis. I wrapped quite a bit of the database in a few minutes and then showed what another 45 minutes of work could do with Rails. I’ll tarball that code and post it online soon.

Alex Bunardzic found it practical. I’ll take that as a compliment. ;-)

Earlier, I noticed this blog entry by Chris… where he said, “PostgreSQL also seems to be growing more briskly among the database category, while MySQL declines modestly. I guess that’s good news for Robby.” What exactly made me happy? This bullet made by Tim O’Reilly on Radar in his post, State of the Computer Book Market, Part 2.

“A surprise to many may be the strong growth of PostgreSQL, up 84% over a year ago. We’ve also been hearing some signs of growth in the Postgres market from our “alpha geek” radar, with reasons given including better support for geo data, and better handling of very large data sets. New companies like Greenplum and EnterpriseDB have also brought a little focus to this market. We’re updating our PostgreSQL book, and watching this market closely.”

That’s awesome! Go PostgreSQL!

Then to my surprise, I was contacted by CRN (again) to get my thoughts on MySQL’s awesome storage-engine plugin system... which showed up a few hours later in this article. The writer of that article managed to goof my last name (Robby Hill?)... and hopefully that gets resolved soon. ;-)

As I said at Canada on Rails in front of 250 people, “I find databases… sexy.”

(free desktop wallpaper!)

Why Rails? Why PostgreSQL?

Rails.. that’s a no-brainer.

PostgreSQL? Well.. they have compatible licenses… no dual-license smell when your trying to sell your application as a complete solution… and as Rails is database agnostic... there is no reason not to give PostgreSQL a try.

Who uses PostgreSQL on Rails?

If your using PostgreSQL on Rails… email me... I’d love to hear and share your story on my O’Reilly blog, like I did with Derek Sivers and Jeremy Kemper of CDBaby a few months ago, which you can read here.

again… I find databases sexy...

If your a PLANET ARGON hosting customer… you can follow these instructions to install PostgreSQL on your PLANET ARGON hosting account.

1 According to the Rails convention (and by me)... any database created pre-Rails or doesn’t follow the conventions is considered legacy. ;-)

Older posts: 1 2 3 4