RailsConf Europe and resources_controller
September 19th, 2007
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:
@userin one and@postin 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_pathandpost_tags_pathin 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.
September 19th, 2007 at 04:02 PM
For anyone who wants the demo project that I was showing at the BoF it's at http://svn.ardes.com/railsconfeurope/forum
September 20th, 2007 at 10:04 PM
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:
which is identical to:
http://pastie.caboo.se/99180
October 4th, 2007 at 09:06 AM
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.
October 9th, 2007 at 07:29 PM
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 :)
December 7th, 2007 at 10:53 AM 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!
April 2nd, 2008 at 10:07 AM really good LRUG presentation last night