A couple of months back, I realised that two of my projects ( Generous and Catapult) could do with the help of the theme_support Rails plugin. Discovering that it didn’t play nicely with Rails 2.1, I created a fork on github and hacked at the _pick_template method to get it to do what I wanted. It turned out a few people were interested in having the plugin work with Rails 2.1, some of whom used more of the plugin’s featured than I need, and a few further forks emerged. I’ve been meaning to work through them and merge together the best bits, but the impending release of Rails 2.3 stopped me in my tracks.

I’m particularly keen to upgrade to 2.3 because Catapult generates a lot of routes and 2.3’s improved route handling should save us quite a bit of RAM and a number of cycles. So it was rather frustrating to find that yet again a new release of rails broke the plugin. Many hours later, working my way through the render path and trying to find the optimal solution, I’m not quite there, but it sort of works and seemed worth writing up:

It turns out that for most templates there’s a single point we can patch that will handle things. ActionView::Base#view_paths returns an instance of ActionView::PathSet which is an augmented Array that ActionView consults to find a template that matches its current requirements. By overriding that method we can check to see if a theme should be active and add that theme’s folder to the set of paths to be consulted.

module ActionView
  class Base

    alias_method :theme_support_old_view_paths, :view_paths

    def view_paths
      paths = theme_support_old_view_paths

      if controller and controller.current_theme
        theme_path = File.join(RAILS_ROOT, "themes", controller.current_theme, "views")
        if File.exists?(theme_path) and ! paths.include?(theme_path)
          paths.unshift(theme_path)
        end
      end

      paths
    end
  end
end

The hitch is that this doesn’t work for layouts, which take a slightly different path. In my case, that’s not a huge deal, but it’s a major omission for other uses. I’ve also not yet tested the actionmailer handling.

You can track progress in a branch on GitHub. I’ll post here as I make more progress, but would welcome any contributions from the rest of the community.

UPDATE (10pm): I just checked in ActionMailer support. More on that tomorrow.