One of my first hobby projects in Ruby on Rails, and for sure the longest living, is called Dinnerlyzer. It is a small, simple, pink (!) application that my girlfriend has used to plan our meals and the required shopping for several years. So far she is the only user, but a while ago I found myself wanting to add a user model and open up the application for multiple users. This meant that I had a lot of objects (recipes, ingredients, shopping lists, etc.) that needed to be associated with a user – the owner. It also meant that some objects should be shared between users (like the ingredients) while other should be private (like the shopping lists). This, in turn, meant that I stood with the prospect of adding a lot of filtering and setting of the correct user in my controllers.
Last week, I was hacking away at another hobby project with a couple of friends (one that will of course make us all zillionaires at some point in the future), where we found ourself wanting to be able to run the same application for multiple sites, but using the same physical backend. This meant the introduction of a Site object, associating almost all existing objects with a specific site, and – again – the prospect of adding a lot of filtering and setting of the correct site in the controllers.
In both cases I could have chosen to just go into the controllers and add the appropriate code to make sure all lookups and deletes was filtered by User or Site, respectively, and that all inserts and updates got these entities tagged on as well, but it just didn’t seem very DRY. It was too much work, it was not fun, and it was repeating myself.
My first impulse was to use observers. It is a Rails classic to use a UserObserver to make sure that fields such as creator_id or updater_id are set the currently active user. This is, however, done per class and not per controller, so if you want to differentiate, say, to filter on the owning user depending on which action has been invoked, you are generally out of luck. (Generally, because you can of course always hack your way to a solution.)
Then I asked Uncle Google for help, and – lo and behold – I found the Scoped Access plugin. Rails has had the with_scope method for a long time, but to my understanding it is not quite as powerful and DRY compared to this plugin. Let me give an example:
In Dinnerlyzer, I needed to restrict all access to recipes per user. I installed the Scoped Access plugin, and added this code to my RecipeController:
class RecipesController < ApplicationController
scoped_access Recipe
..
protected
def method_scoping
ScopedAccess::ClassScoping.new(Recipe, :user_id => current_user.id)
end
end
The scoped_access call at the top ensures that the method method_scoping is called to return the appropriate scope for all requests on the Recipe object. Not just lookups, but also creation, editing and deletion.
In another controller, I wanted all users to be able to browse and view all ingredients in the application, but only to be able to edit and delete ingredients added by themselves. This was done as simple as:
scoped_access Ingredient, :except => [:index, :show]
In the other application, we were able to employ a similar strategy, allowing us to very fast and in a quite DRY way to add these access restrictions to our controllers.
It’s the day after the second BarCamp in Copenhagen ever, and the first one that I’ve been lucky enough to participate in. Heck, I even presented at it, contributing with what you can is the whole point of such an arrangement, right?

Copyright © 2008: Thomas Kristiansen
Here is some mixed impressions from night:
My own presentation turned out to be only the second-most geeky of the night (MC’s on IPv6 being number one on that list), and I think it went pretty well. Perhaps I shouldn’t admit this, but it was a bit of rip-off from Dr. Nic’s talk at RailsConf Europe 2007, although my attempts at being funny, while keeping up the proud tradition of ridiculing non-Ruby programming languages, was to compare PHP to a Chihuahua dog and C# to Uffe Holm.
It turned out, however, that my last slide was what generated the most response. It was nothing more than a screenshot of the heroku.com in-browser Ruby on Rails editor and recommendation of using this innovative service to get started with Rails. Perhaps I should do a full article about Heroku in the near future.
To those of you who were at BarCamp: Great meeting you! To those who weren’t there: Don’t miss out next year! And finally a big thanks to Henriette and Thomas for organizing the event, to Beaconware for hosting it, and not least: Thanks for the food and beers!
I’ll be giving a talk at BarCamp Copenhagen January 25th. I haven’t decided exactly what I am to talk about yet, but it is going to be on the tech track (called Geeky Sh*t), and it is going to be about some facet of Ruby on Rails – or perhaps just Ruby.
I could give a general introduction to Ruby, and to Ruby on Rails, but I guess the technical people at this conference are probably curious enough to have tried out the language and framework by themselves, and I know that a few of them will be equally or better skilled Ruby programmers than me, and therefore utterly bored at a basic introduction.
I could of course be preaching test-driven development (TDD) and show how Rails makes this approach quite easy, but haven’t TDD’ed much in my latest projects, because I was tired of having this huge, always-breaking test suite, which rarely caught any real bugs, and mostly just indicated that my tests was buggy. I’m starting to get a feeling that Cope is right when he says that unit testing can be harmful.
When I got the opportunity to start working full time with Rails – well, not full time, since I’m still a student, but all my 20 work hours a week – last spring, I was quick to decide on basing most of the sites on Radiant CMS to get a bit of common infrastructure. This turned out to be a good choice, but it did put a few limits to my opportunities for using the newest Rails features, as I had to follow the Rails version used by Radiant. As of today, Radiant has still not been upgraded to Rails 2.0. I have gained a lot of insight on how to get the most out Radiant – especially through extensions – but it is probably pretty irrelevant to hear about if you don’t use Radiant or are planning – or do not even use Rails at all (what a horrible thought!).
But I’ve learned a lot of what I think fits into the category of Ruby metaprogramming writing these extensions. I have had to override and extend quite a few methods and classes in Radiant through extensions, to get it act like I needed it to, and that has not been entirely painless. There are different techniques depending on whether you need to add or override stuff, and whether it is class methods or calls, or instance methods. You also have to consider when to use alias and alias_method, and you have to know the difference between them.
In fact, there is one trick I feel like sharing right here: How to re-enable sessions for a controller, if you can’t just (or at least don’t want to) remove the session :off statement in the original controller code. In this case I needed to re-enable sessions for the Radiant SiteController without modifying the Radiant code. This code did the trick:
module SiteControllerExt
def self.included(base)
base.class_eval {
# This reenables the session for the SiteController - session :on does not work!
session :disabled => false
}
end
end
You also need to include this module in SiteController in your extension’s activate method, or in environment.rb in other Rails apps:
SiteController.send :include, SiteControllerExt
Of course there is a lot more to metaprogramming than class_eval, but it is a start. I think this could a good subject for my talk, I just hope it is not too geeky for the audience. I might want to throw in some general dynamic vs. static typed languages and the whole – in my opinion very nice – duck typing philosophy of Ruby, just annoy the C# and Java guys. Yeah, this is going to be interesting – there is still a few open spots left at BarCamp Copenhagen!
Hello, I'm Casper Fabricius. I have developed for the web for 10 years, and have been enjoying Ruby on Rails for the past 5.
My experience covers communities, shopping solutions, multi-language sites, heavy back-end lifting and a wide selection of more traditional websites. I like to integrate Ruby with Java and .NET through JRuby and IronRuby when it makes sense. I am passionate about test- and behavior-driven development, but at the same time I am pragmatic and believe in getting things done.
I live in Copenhagen, Denmark, where I work for a fantastic company: Podio. I do not currently take on freelance assignments.