Fly-mart.com has been live now since the first of the year, yeah I know the logo sucks – I’m working on that!  Traffic has been steadily growing, though the site is still in beta and is not taking payments, I’ve been very happy so far.  One thing that’s been heaven’s sent is HopToad.  Despite being diligent with regard to testing, some things slip.  HopToad is right there and in one particular incident, I was busy fixing the code before the customer even had a chance to finish his email to support (me).  Good stuff!

Anyway, one of the issues I ran into early in the project was the inability on Heroku’s app environment to write to the file system. If you’re using “paperclip” – this is kind of an issue, though it’s relatively easy to work around,  Paperclip can easily integrate with Amazon S3.  The big problem though came with testing.  For some, still unexplained reason, I was never able to get my Cucumber or RSpec tests to successfully connect to the S3 service, I consistently got a connection exception.  I didn’t really think this was worth chasing down as ultimately I really didn’t want the tests to hit S3 directly.  My first thought was to use some sort of web tier mock to trick the code into thinking it was talking to S3.  There were a few examples I found regarding how to get this to work but again I had little luck with my own codebase.  I’m not sure it was because I choose R3 or some other reason, but again no joy.

I was thinking that what I really wanted was the ability to define different behavior depending on the environment.  For example, production and development I wanted actual S3 calls and for testing I would be perfectly happy to have my Paperclip image files land on the local hard drive.  I had a conversation with a good friend, Ryan Daigle who agreed with the approach and could also offer some code to get me bootstrapped.  What follows is the relevant code with commentary.

Step 1 - Modify your app/model/asset.rb class slightly

The thing to notice is that the normal paperclip code that you’d expect in your asset class it replace by the “stores_file_as” helper.  Most of the paperclip configuration as well as the mechanism to detect the environment and act accordingly has been moved into there.

class Asset < ActiveRecord::Base
  include Helpers::AssetStorage
  
  
  before_validation :clear_asset
  belongs_to :ad, :polymorphic => true
  
  stores_file_as :image,
                    :styles => {:micro => "75x43", :thumb => "128x95", :medium => "300x300", :large => "500x500"}
  validates_attachment_presence :image
  validates_attachment_size :image, :less_than => 1.megabytes
  validates_attachment_content_type :image, :content_type => ['image/jpeg', 'image/gif', 'image/png']
  
  def delete_asset=(value)
    @delete_asset = !value.to_i.zero?
  end
  
  def delete_asset
    !!@delete_asset
  end
  
  alias_method :delete_asset?, :delete_asset
  
  def clear_asset
    self.image = nil if delete_asset? && !image.dirty?
  end
  
end

# == Schema Information
#
# Table name: assets
#
# id :integer not null, primary key
# ad_id :integer
# created_at :datetime
# updated_at :datetime
# image_file_name :string(255)
# image_content_type :string(255)
# image_file_size :integer
# image_updated_at :datetime
#
view raw asset.rb This Gist brought to you by GitHub.

Step 2 - Add a app/helper/helpers.rb module

The idea here is to delegate the heavy lifting of the paperclip configuration to the helper module but more importantly to detect the environment and configure the appropriate behavior. In my case, I wanted 'dev' and 'prod' to use the actual S3 environment while the test environment should use the local file system. Not only does this keep the charges lower for S3 but has the added benefit of speeding up the tests. Alternatively you could externalize the configuration in a DSL but I really didn't see the point.
module Helpers

  # Conventient way to setup filesystem attachment uploading when in dev/testing
  # and use S3 otherwise
  module AssetStorage

    def self.included(within)
      within.class_eval do
        extend ClassMethods
      end
    end

    module ClassMethods

      def stores_file_as(asset_type, opts = {})
        filename_interpolation = opts[:filename_interpolation] || ':style.:extension'
        options = use_local_storage? ?
                filesystem_default_options(filename_interpolation) :
                s3_default_options(filename_interpolation)
        options = options.merge(opts)
        has_attached_file asset_type, options
      end

      private

      def use_local_storage?
        @use_local_storage ||= !(Rails.env.production? || Rails.env.staging?)
      end

      def s3_default_options(filename_interpolation)

        # Akamai URL -> origin URL -> Rails env
        # N/A -> origin.staticassets.development.theslap.digitaltoniq.com -> development
        # staticassets.theslap.digitaltoniq.com -> origin.staticassets.theslap.digitaltoniq.com -> staging
        # staticassets.beta.theslap.com -> origin.staticassets.beta.theslap.com -> beta
        # staticassets.theslap.com -> origin.staticassets.theslap.com -> production
        {
          :storage => :s3,
          :s3_credentials => "#{RAILS_ROOT}/config/s3.yml",
          :path => "/:style/:filename"
        }
      end

      def filesystem_default_options(filename_interpolation)
        {
          ## Add any local file system options you may want here ...
          # :url => "/assets/:class/:slug/#{filename_interpolation}",
          # :path => ":rails_root/public/assets/:class/:slug/#{filename_interpolation}"
        }
      end

    end
  end
end
view raw helpers.rb This Gist brought to you by GitHub.
Happy Hacking, Peter

{ 0 comments }

I figured the first thing that I ought to do it to figure out the answer to the question Rails 2.x or 3?

To the initiated, that’s probably a pretty simple question but for someone like me, coming back after a long “it’s not you, it’s me” thing, it wasn’t that easy.

First there was the stability question.  R3 is relatively new, which led really to two questions: Is it stable and is there enough documentation out there to get me going?  I didn’t really dwell on the stability question long.  First off, I know that the Ruby/Rails community (for the most part) are test Zealots.  That and there’s tons of eyeballs out there on the code also brought me great comfort.  What I wasn’t sure of though was all the gems and plug-ins.  How much of a departure was R3 from R2.x and how long will it take the ecosystem to catch up.

The documentation question also had nested concerns.  The Rails community is great at producing how-to’s and tutorials but again, how fast are they to react to the new Rails version?  My normal “go to” sources peepcode.com and railscasts.com seemed to not quite be there yet, though working on it.

I also wanted some industrial strength goodness that I could tap.  I don’t think I could take another “build a blog in 15 minutes” tutorial.  Though interesting and helpful, many of these resources don’t really delve into the nitty gritty of a production application and cover deployment, testing and some of the other tips and tricks hard won by seasoned rails developers.

I was lucky enough to come upon Michael Hart’s excellent Rails 3 tutorial “Ruby on Rails Tutorial: Learn Rails by Example”.  As it turned out it was almost exactly what I needed.  Though the example used in the book is the often used “Twitter Clone”, it was comprehensive enough to be interesting and engaging.  Most valuable though was picking up tips and tricks and helpful plug-ins along the way.  Believe it or not, I had never used git before.  When I’m not stuck with CVS, I’m likely using SVN.  Similarly, Hart introduces TDD via RSpec, Heroku, setting up your environment and of course all the R3 goodness including a vast universe of gems that have proven invaluable.

Up for next week … I’ll start researching/brainstorming a workable layout and doing battle with CSS and ERB!

{ 0 comments }

We’re back together – me and Ruby! (Part 1)

December 8, 2010

The Back Story So as an architect for a *big* networking company, I really don’t write a whole lot of code.  I guess that’s what happens as our careers move forward.  I’ve traded my syntax color highlighting and code-completion for bubbles and arrow.   I’m probably a glutton for punishment but Viso doesn’t give deprecation [...]

Read the full article →

Shakeout Glastar Flight – a Movie Short

August 12, 2010

Yeah, Yeah, it’s been forever since I’ve posted.  I’ve been super-busy though… really!  As some of you may know, I decided to give the Glastar, affectionately known as “Whistler” a brain upgrade.  My experience with my Blue Mountain Avionics EFIS was – how should I put this delicately.. “mixed”.  I can’t be too harsh on [...]

Read the full article →

The Two Categories of Kit Built Aircraft…

May 20, 2010

“I’ve come to realize that there two categories of kit built airplanes: 1) Under construction and NOT flying  2) Under construction AND flying.” The first long flight of the season is always interesting.  It’s even more interesting if the flight is following major maintenance which was the situation this year.  At the end of last [...]

Read the full article →

Knocking the Rust off My Piloting Skills

April 27, 2010

A funny thing happens when you spend 10 years of your life building an airplane: You don’t fly much.  The other thing that happens is that sooner or latter you actually have to get in the airplane you built and fly it!  Should I worry about the left-over parts I had after I finished?  All [...]

Read the full article →

HTML Scraping, Starring: Ruby, HPRICOT and Firebug

September 9, 2009

I had a really sticky problem.  I’m building a web 2.0 application that aggregates data from disparate social media sites.  The good news is that MANY sites have really great, REST API’s while many do not.  My nemesis was Google Blog Search.  Sorry Charlie, no API! What to to? I’ve burned several nights trying to [...]

Read the full article →

Six Things to Keep in Mind when Considering Code Reviews

February 17, 2009

In general, I’m not a huge fan of code reviews but they can be an effective tool if they’re kept in check. A co-worker asked me to put together some talking points about code reviews, which I did, regarding some of the things I thought would be material to keep in mind for a code review process. I thought they might be generally useful, so I’m posting them here.

Read the full article →

2 Minute TIps – Learn how to set up a Google Alert!

January 23, 2009

This is a bit of an experiement. I wanted to create a series of “2 Minute Tips” – video screen casts that show how to do something specific in a relatively short amount of time.

Read the full article →

Abundance and Gratitude

January 7, 2009

You can’t escape it.  Each morning when I slide the paper out of it’s plastic baggie or turn on CNN, there it is: the constant drumbeat of bad news.  It rains down on us unmercifully like a torrent.  I catch my optimism waning more than I’d like to admit.  I think doubt is natural when [...]

Read the full article →