Testing Feedzirra

For one of my side-projects I’m using Feedzirra, a robust feed parsing library. Since we all TATFT I wanted to test parts of my code that depend on feed parsing.

The glitch is that Feedzirra doesn’t work with FakeWeb, since it’s using cURL for remote connections. However cURL supports file:// protocol, so you can fake external requests with local files. I’m using Shoulda in the following examples.

app/models/feed_storage.rb
# Excerpts extracted from model

class FeedStorage < ActiveRecord::Base
  def parse
    if self.marshaled.nil?
      parser = Feedzirra::Feed.fetch_and_parse self.feed.url
      entries = parser.entries
    else
      parser = Marshal.load self.marshaled
      parser = Feedzirra::Feed.update parser
      entries = parser.new_entries
    end

    self.update_attribute :marshaled, (Marshal.dump parser)
    entries
  end
end
test/unit/feed_storage_test.rb
# Excerpts extracted from model's tests
class FeedStorageTest < ActiveSupport::TestCase
  context "a new feed" do
    setup do
      @feed = Factory :feed
      @feed.update_attribute :url, "file://#{URI.escape(File.join(File.dirname(File.expand_path(__FILE__, Dir.getwd)), "..", "fixtures", "full_feed.rss"))}"
    end
    should "setup a new parser and parse all entries" do
      assert_equal 50, @feed.parser.parse.length
    end
  end

  context "a parsed feed" do
    setup do
      @feed_path = "#{URI.escape(File.join(File.dirname(File.expand_path(__FILE__, Dir.getwd)), "..", "fixtures"))}"
      `cp #{File.join @feed_path, "full_feed.rss"} #{File.join @feed_path, "feed.rss"}`

      @feed = Factory :feed
      @feed.update_attribute :url, "file://#{File.join @feed_path, "feed.rss"}"
      @feed.parser.parse

      `cp #{File.join @feed_path, "updated_feed.rss"} #{File.join @feed_path, "feed.rss"}`
    end
    should "parse all new entries" do
      assert_equal 1, @feed.parser.parse.length
    end
    teardown do
      `rm -f #{File.join @feed_path, "feed.rss"}`
    end
  end
end

The logic behing FeedStorage is quite simple - for every feed in the database I store its feed parser (a marshaled Ruby object, might switch to something else if I run into performance issues). Feed class requires valid urls for url field, hence the update_attribute call.

Feel free to drop me a line in the comments - I’m sure there’s some room for improvements!

My Tools of the Trade

Inspired by Mike Gunderloy I thought I’d share my setup used for everyday development.

Hardware

Plain & simple - 15" MacBook Pro, mid-2009. Just switched from 13” white MacBook and I love the speed boost it gave me. I find Wireless Mighty Mouse very comfortable and useful, and it frees up an USB port. Apple Keyboard (full size) is a clear win. 500GB disk used for Time Machine backups and an additional 320GB 2.5” drive for extra storage.

At the office I use an extra 19” display - good enough to display logs.

And yeah, iPhone, of course.

Software

  • Snow Leopard - early adoption wasn't too painful after all, and it actually might be running a little faster than good ol' 10.5,
  • Safari - my primary browser, used both for development and everyday browsing, boosted with heavily customized Glims,
  • Quicksilver - as I heavy keyboard user I find this application a must, goes great combined with Dockables,
  • 1Password - can't imagine a better credentials manager, I feel completely lost without it,
  • Adium - I don't like IM that much, but we use it at work. I always run beta versions of Adium, they're stable and offer some nice features!
  • Firefox - used from time to time for development, when Safari's debugger's not enough and with the decline of Firebug's quality and workflow Safari stands strong,
  • Fluid - standalone web applications generator, I use it for Google Reader, Instapaper and Blip with custom styles and userscripts,
  • ForkLift - did I mention I'm a keyboard guy, with a strong Norton Commander / Total Commander background?
  • FStream - I can't focus on work without music and this is a simple Internet radio streaming application,
  • GitX - still working out my git workflow and GitX helps a lot,
  • GrandPerspective - shows a graph of files and folders the hogging hard drive, really useful,
  • HTTPScoop - used for local debugging, for online testing I prefer Hurl,
  • Paperless - my document repository, invoices, agreements and such,
  • Parallels - with Windows XP, Ubuntu and Ubuntu Server for cross-browser tweaks and server setup testing,
  • Pixelmator - I'm the last person who should do anything with graphics but sometimes I really have to. Pixelmator's learning curve is acceptable and it does everything I need too,
  • Sequel Pro - Sequel's Pro nightlies are stable and robust with some features that current stable's missing,
  • SizeUp - again, keyboard lovers, resize / move your windows with a 4-finger combos,
  • Skitch - great for screenshots with annotations,
  • TextMate - enough said,
  • Things - great task manager with phone sync (I really need a phone sync for offline usage),
  • tunnelblick - for my company's VPN,
  • Tweetie - I'm more a reader than writer and Tweetie's great for that.

There’s also a few other applications that I use but those are essential - I keep them in my Dock.

Hosting

For my pet projects and fun stuff I use IntoVPS with Server Density monitoring. For production we have an in-house server farm. I’m looking into SliceHost / Linode for production of some smaller private stuff.

Switching Ruby on Rails development to Snow Leopard

Just a couple of random notes on switching to Snow Leopard.

taf2-curb gem

Compiling taf2-curb also requires (like memcached does) a custom environment flag:

sudo port install curl
sudo env ARCHFLAGS="-arch x86_64" gem install taf2-curb

Subversion bundle in TextMate

I didn’t quite work out all the issues with TextMate's Subversion bundle, but at least CommitWindows pops up (I still can’t revert changes). Setting TM_RUBY variable to /usr/bin/ruby (for default Snow Leopard Ruby) in Properties / Advanced / Shell Variables tab fixes this issue.

Compiling memcached gem on Snow Leopard

For production at Blip we’ve recently switched from memcache-client to Evan Weaver’s memcached gem (performance!). Compiling it on Snow Leopard for development requires ARCHFLASH to be set to -arch x86_64.

To fix this just uninstall and reinstall memcached:

sudo gem uninstall memcached
sudo env ARCHFLAGS="-arch x86_64" gem install memcached<

And you’re done!

Using tunnelblick with Snow Leopard

I lost quite some time figuring out how to run tunnelblick on Snow Leopard.

As opposed to common sense - you should not use the latest builds (3.0b18, 3.0b16 - at the time of writing this post) of tunnelblick. I’ve managed to successfully connect to my VPN with tunnelblick 3.0b14.