taylorbarstow.com

simple_pagination

I just pushed a new project to github: simple_pagination. It is a dead simple, standalone pagination library.

Some might say I’m reinventing the wheel, but I don’t see it that way. I realize there are some great pagination libraries for Rails/ActiveRecord (will_paginate), and I’m not trying to compete with or replace them. Rather, I see simple_pagination as a compliment to these projects. It is useful when you aren’t using ActiveRecord but you have data to page through… such as when you are consuming search results from a remote API.

(In fact, if mislav wanted to, he could refactor will_paginate to use simple_pagination. I doubt he wants to though. I know I wouldn’t want to.)

I hope other people find this useful—I know I’m tired of writing pagination logic when dealing with non-ActiveRecord data, which I am doing more and more of. Anyway, enjoy!

Daemons in Ruby; or, Frustration

Over at unbiasd, we use a couple of daemons to keep our web interface snappy. Rather than letting our mongrels sit around and handle long running tasks (such as outbound web requests), we offload these responsibilities using the delayed_job plugin. Currently we’re using collectiveidea’s branch because it includes a nifty script to run delayed jobs in a daemon environment using the daemon generator plugin.

The bad news? The daemon crashes all the time. Sure, I could write a monitor daemon to restart it when it crashes (daemon generator even includes a prepackaged one of these). But that seems somehow wrong—what if my monitor starts crashing? Write another monitor? What if that starts crashing? In programming I believe in finding and solving the real problem rather than ignoring it and programming around it. The former is akin to an elegant solution, the latter to brute force.

So how do I proceed? Step 1 is clearly to remove all third party code—or at least to become intimately familiar with it. Ideally I’d like to keep using delayed_job, so I’m going to whittle away at the other third party code first. This means getting rid of my daemon generator crutch. This has some obvious advantages:

  1. I can use tobi’s delayed_job, which is clearly more up to date than collectiveidea’s
  2. I can learn the ins and outs of writing daemons in Ruby
  3. Hopefully I can write a good daemon and submit it back to tobi (with the magic of github)

So this is an introductory post—a prelude to a journey. More to come.

The Ruby Community Rocks

The acts_as_rated plugin (see also: rdoc, github) just saved me hours of work.  Ruby is a (really, really) great language and Rails is a great framework, but I’m quickly realizing that the Ruby and Rails communities are more valuable than either of those two points.  There is a true spirit of sharing.  Everyone is working on their own projects, but they always seem to pull out the really useful bits and publish them as gems or as Rails plugins.  To me, this is what open source is all about.

I’m not 100% sure why this community seems so much more enthusiastic about sharing than other language or framework oriented communities, but I do have some ideas.  Maybe I’ll explore that later.

Rails: Augmenting ActiveRecord::Base#find

Let’s say you want to modify a given ActiveRecord class such that all #find calls will, by default, sort by a given column. I ran into this the other day, and I wasn’t quite sure how to do it. Turns out it’s actually pretty easy (though not 100% trivial for the noob):

class User < ActiveRecord::Base
  def self.find(*args)
    options = args.extract_options!
    options[:order] ||= "last_name ASC, first_name ASC"
    super(*args.push(options))
  end
end

This snippet will cause User#find calls to by default sort the results first by last_name, then by first_name. If, however, you specify the :order option when calling #find, this method will respect your choice.

Caveat: I’m not sure when Array#extract_options! showed up in Rails’ ActiveSupport library, but it’s at least there as of 2.1.0.

Ruby: HTTPClient is was Sloooooow

Update: A new version of HTTPClient has fixed my slowness problems. More info in the comments.

Is this just me? I think it must be—I am getting terrible performance using HTTPClient vs Net::HTTP. I was looking for an alternative to Net::HTTP because its API is ugly as hell, but the performance difference leaves me with no choice.

Let’s take the example of loading this blog’s last four entries using the Google AJAX Feed API. Net::HTTP consistently takes less than a second to load the results, while HTTPClient consistently takes between 10 and 15 seconds! This can’t be right, I must be doing something wrong…

Here’s the script I’m using to test:

require 'httpclient'
require 'net/http'
require 'uri'
require 'cgi'

def time(label)
t_start = Time.now.to_f
yield if block_given?
puts "#{label}: #{Time.now.to_f - t_start}s"
end

feed_url = "http://taylorbarstow.com/feed/"
url = "http://www.google.com/uds/Gfeeds?v=1.0&amp;amp;amp;amp;amp;output=json&amp;amp;amp;amp;amp;q=#{CGI.escape(feed_url)}"

time "Net::HTTP" do
Net::HTTP.get(URI.parse(url))
end

time "HTTPClient" do
HTTPClient.new.get_content(url)
end