Optionally Nested Controllers

Published 16 December 07 by Justin French

I’ve seen this asked a few times in #rubyonrails and #roro IRC channels, so rather than knock up a code example every time, maybe I can just point people here.

The Problem

Some people like nested resource URLs like /people/21/images/45, instead of flat URLs like /images/45, and some people like to have both accessible as options. Rails’ Routing can do this easy. Some people consider these two different resources, so they’ll have an ImagesController and a PeopleImagesController. Others think that’s horribly repetitive for what they’re doing with their code, so they want it all to go through one ImagesController with an optional parent object or scoping.

This is for those people, scratching their heads, wondering how that’s done cleanly.

A Solution (though most certainly not the only solution)


 class ImagesController < ApplicationController
   def index
     @images = parent.find(:all)
   end
   def show
     @image = parent.find(params[:id])
   end
   def new
     @image = parent.new
   end
   # ...
   protected
   def parent
     params[:person_id] ? 
       Person.find(params[:person_id]).images :
       Image
   end
 end

But what does it do?

Given the URL /people/24/images/..., params[:person_id] will be set. If it's found @parent returns an images collection scoped to that person upon which we can perform our find, new, create (etc) methods on. If it’s not present, we just do them directly on the Image class.

It’s scoped to the person if there is one in the URL, and isn’t if there isn’t.

There are many ways to tackle this kind of problem, and plugins like make_resourceful do similar things and are a great kick in the right direction.

Options

What is this?

portrait of Justin

This is the online home of Justin French, a designer & web application developer located in Melbourne, Australia. I like finding ways to make things work better. I like clarifying and simplifying. I like to understand how you understand things.

» read more

Subscribe to my feed

Follow me on Twitter

@justinfrench

More Notebook Articles

Show more notebook articles

Search