Ian White

I've been chatting to a few people at RailsConfEuropoe about resources_controller, so I thought I'd say a few words about waht it's key features are, and about RC at RailsConfEuropoe in general.

Key features

There's a few plugins out there that try and solve the same sort of problem - DRY up RESTful controllers. I believe that RC's standout features can be seen when considering how to write controller for a polymorhpic has_many relationship.

Polymorphic Tags

So you want to tag a bunch of models, and so you sure the :polymorphic has_many assoc, and make a Tag model with belongs_to :taggable, :polymorphic => true.

You want tags to be nested under a bunch of different resources like this:

  map.resources :users do |user|
   user.resources :tags, :controller => 'user_tags'
  end

  map.resources :posts do |post|
   post.resources :tags, :controller => 'post_tags'
  end

Standardly, you'd then have to write two controllers: UserTagsController, and PostTagsController, and map the above two nested routes to those different controllers. These would be essentially the same functionality except:

  • they would load different models in before filters: @user in one and @post in the other,
  • they get the post from different collections (@tag = @user.tags.find(params[:tags_id]) vs @tag = @post.tags.find(params[:tags_id])),
  • they redirect to different routes on completion of certain actions user_tags_path and post_tags_path in the other.

To do this, even with plugins to dry everything up, you still need to create two (or three, or four) controllers for tags - all doing essentially the same thing.

it gets worse. You'll need a bunch of different views - because they all need to link to urls relative to the enclosing resource. Suddenly you've got a lot of really similar code - or some really ungly hacks in your views.

(and all of this gets much worse if you have deeply nested routes)

Polymorphic tags with resources_controller

resources_controller (used in the default way) inspects the route that was used to invoke the controller. From this, it:

  • loads all of the enclosing resources,
  • uses the immediately enclosing resource as the resource service (the object that we send find and new to to - in the case of /posts it would be the Post class, in the case of /post/1/tags it would be the @post.tags association),
  • does some method missing magic so that you can refer to all named routes relative to the current resource

All this means you just need to write one controller, and one set of views for Tags

Here's some sample code

  class TagsController < ApplicationCntroller
    resources_controller_for :tags
  end

in show.html.erb:

  <%= link_to 'tags', resources_path %>

The above will be user_tags_path(@user) in one case and post_tags_path(@post) in another.

It gets better, you can refer to the enclosing resource as well:

  <%= link_to "back to #{enclosing_resource_name.humanize}", enclosing_resource_path %>

And if you have routes like /users/1/posts/2/tags, and /posts/1/tags, the you can use the same view for posts:

  <%= link_to 'tags', resource_tags_path %> # in /users/1/posts/2/tags will be:
                                            # user_post_tags_path(@user, @post)
                                            
  <%= link_to 'tags', resource_tags_path %> # in /posts/2/tags will be:
                                            # post_tags_path(@post)

That's just some of the features, I'd love to get feedback, patches, bug reports, etc. There are links to RC via svn, and rdoc on our plugins page

BoF and RejectConf

Man, I've got a lot to learn about presentations...

I gave a BoF at RailsConfEurope07 session on resources_controller - I was expecting about 10 people and a round table discussion on taking the pain out of RESTful controllers. About 50 or 60 people turned up so we ended up all crowded round a couple of laptops. But everyone was friendly and there was no heckling. Paolo, who gave the incredibly entertaining talk on widgets, took some photos

There was, however, plenty of heckling at the RejectConf talk. The format was 5 minutes of slides, 20 seconds automatic countdown for each one. I wrote the presentation during the day, and ran through it with my wife before hand. It sucked - way too much info. So I cut it down.

However, I was first up, and gave the audience the choice of the insane, or sane, talk, and they chose insane. I tried to get across about 1/2 an hour's worth of stuff in 5 minutes, and the audience looked as though they were in a wind tunnel. It was a great icebreaker for the other speakers though. I'll post the slides here in due course.

RejectConf was simply awesome by the way. The berlin ruby user group rocks.

6 Responses to “RailsConf Europe and resources_controller”

  1. Ian

    Ian Says:

    For anyone who wants the demo project that I was showing at the BoF it's at http://svn.ardes.com/railsconfeurope/forum

            To see the app being created incrementally, start at rev 6, and look at the diffs.
    
  2. Hendrik

    Hendrik Says:

    Hi there!

    I saw your talk at RejectConf and it got me interested. I looked at the code and was wondering why you didn't derive the model name from the controller name.

    As I wanted to play around with RSpec anyway and you're using it for testing in your plugin, I created a small patch for so that you can do this:

            `class DogsController < ActionController::Base
              resources_controller
            end`
    

    which is identical to:

            `
            class DogsController < ActionController::Base
              resources_controller :dogs
            end
            `
    

    http://pastie.caboo.se/99180

  3. Ian

    Ian Says:

    Hey Hendrick - sorry - your comment got marked as spam, and I was away on a holiday for a week.

    RejectCOnf was a blast eh!

    Thanks for your nice bit of magic there. I'm wondering if it's a little too magical (It doesn't save much typing - and the typing it does save serves as good documentation). But I'll post it the google group http://groups.google.com/group/resources_controller and see what people think.

  4. Eleanor McHugh

    Eleanor McHugh Says:

    Would have loved to see your RejectConf performance but we were busy running our own BoF. Still, as someone who's always accused of putting too much content in my presentations I wholeheartedly endorse the "insane" approach lol

    BTW, really good LRUG presentation last night :)

  5. Rasheed Abdul-Aziz

    Rasheed Abdul-Aziz Says:

    Hey Ian, Fantastic group of plugins (rc, rf and rfrc). Slowly getting to grips with them and using them in a simple demo 'contact' app for our flex plugin. Thanks for your efforts!
  6. iddaa

    iddaa Says:

    really good LRUG presentation last night

Sorry, comments are closed for this article.