Delayed::Job comes out of the box with a startup script that relies on the daemons gem. to start and stop worker processes.  Problem is, we’ve never actually had it work. After browsing around our options we decided to give daemonizer a go.  The main advantage we saw to daemonizer is that you simply define a single “Daemonfile” in your project’s root (similar to a Gemfile or Rakefile) explaining how to set up each processes environment.

My Daemonfile looks like this:

The only minor problem we had was with daemonizer’s gem dependencies clashing with my apps.  We have submitted a patch to make sure that daemonizer uses bundle if the project has a Gemfile present.

If you’ve perused the source of any moderately complicated Rails application you are likely to have come across the Single Table Inheritance (STI) pattern.  STI allows you to have polymorphic models all stored in the same table or collection. It may be best to give you an example:

As you can see from the example, we have three models, Meat, Bacon and ChunkyBacon all using the “meats” table for storage.  This is really great, especially if there is common model logic (attributes, validations, life-cycle callbacks, etc) needed for all three models, and extra logic on the child models (imagine ChunkyBacon has a season).

Kimono makes extensive use of STI behaviour throughout it’s model graph, although built upon the Mongoid ORM.  We kept running into problems where we needed to have routes for every new subclass we created and it didn’t really fit the way we wanted the application to work.  The problem is not actually the router (a simple map.resources :meats) works perfectly, but with the route helpers. A call to url_for or link_to when passed in a model instance would throw an exception because there were no routes defined for Bacon or ChunkyBacon.  We started with overriding the helpers (link_to, et al) but soon discovered this didn’t work well enough because the assumptions Rails makes about routing your models go deep.  How deep? To ActionDispatch::Routing::PolymorphicRoutes as it turns out.

In order to create the behaviour we wanted we needed to add a reusable method to climb up a model’s superclass chain checking if the parent is a Mongoid document until it reaches the top of the inheritance tree,  then we needed to patch “build_named_route_call” to use this instead of just using the class of the model being routed.  Enter lib/kimono/routing.rb:

Once that’s done, we simply add an initialiser to patch in the behaviour we want:

Now when we call url_for(@bacon) we get “/meats/1” back.  Thanks Ruby.

Dynamic finders for Mongoid

We’ve been busy over the last while switching a Rails 3 application over from ActiveRecord to Mongoid. In a lot of ways it has gone a lot less painfully than we expected, however one of the main problems we ran into was the common use of dynamic finders in controllers:

Mongoid (at the time of this writing) doesn’t officially support dynamic finders, so we have done one of our “minimum viable implementation” versions, available on Github.  Please feel free to fork and send patches.