sample rails application updated
Courtenay : April 8th, 2007
Update: please see http://sample.caboo.se for the latest version and changesets.
Now with svn repository.
svn://caboo.se/plugins/court3nay/empty_apps/restful_auth_rspec
What's new?
- polymorphic image model
- basic authorization
- around_filters with scoping
Here's a snippet from the image controller. I'm working towards a best-practise example of how to do nested polymorphic resources. If you have a better method, please do tell me.
class ImagesController < ApplicationController
around_filter :load_user
before_filter :load_image, :except => [ :index, :create, :new ]
before_filter :check_auth, :only => protected_actions
protected
def load_user
# todo: support other attachable types here.
@attachable = User.find_by_param(params[:user_id]) or raise ActiveRecord::RecordNotFound
Image.with_scope( :find => { :conditions => ['attachable_id = ? and attachable_type = ?', @attachable.id, 'User'] }) do
yield
end
end
def load_image
@image = Image.find(params[:id]) or raise ActiveRecord::RecordNotFound
end
def check_auth
@image.attachable == current_user or raise AccessDenied
end
public
11 Responses to “sample rails application updated”
Sorry, comments are closed for this article.
April 8th, 2007 at 02:59 PM
This application template is looking very interesting. I’ve been straying away from setting instance variables in my before filters, as it makes the controller code difficult to read (especially in larger applications). Instead, I like the caching trick:
def current_image; @image ||= Image.find(params[:id]; end
…and current_image just gets called all over the place.
April 8th, 2007 at 07:59 PM
Great effort but please change the example to not use .with_scope . With scope is an internal implementation detail of ActiveRecord and its public by mistake. We will probably make the method protected for rails 2.0 .
Besides, it is also conceptionally way to complex for an beginner level example application. It takes a lot of knowledge of the inner workings of AR to understand how to use it.
April 9th, 2007 at 09:38 AM
Hey Court,
regarding polymorphic nested resources, the most important thing to remember is polymorphic.
Before I explain what this means - I’ve had this conversation a few times now and there’s always initial resistance because it involves having 1+N controllers (where N is the number of polymorphs you define) and people generally balk at it.
Trust me though, done right this is all very DRY and I’ve used it enough times (using AJAX and postback) to know it’s a sensible approach.
Anyhow, if you try to use a monomorphic controller (images_controller) throughout your app it ends up fairly ugly - loads of conditionals etc.
So the first step is to treat imagescontroller an abstract base class (never directly used in a route) and create specific types of imagescontroller.
I.e. userimagescontroller, productimagescontroller etc.
That way, userimagescontroller knows that the attachable is @user, productimagescontroller knows that the attachable is @product etc etc.
After that, all you need to do is to delegate url helper calls to the right url helper - i.e. when dealing with urls for user images, the imagepath helper calls userimagepath and imageownerpath calls userpath etc.
My resource_fu plugin makes this sort of thing pretty simple.
I’ll hook up with you shortly in caboose to flesh this out a bit more.
Trev
April 9th, 2007 at 09:40 AM
Hey man, really nice work – will help a lot of people learn and use best practices.
April 9th, 2007 at 05:50 PM
Really nice idea to a sample app like this. A couple of comments:
@image = Image.find(params[:id]) or raise ActiveRecord::RecordNotFound
The raise is redundant. ActiveRecord::Base.find() already raises a RecordNotFound when you pass an id which doesn’t exist.
I would also change the Image.with_scope stuff and just stop doing Bare-Model Finds and replace with @attachable.images.find(params[:id]) (or probably @user.images.find(params[:id]) since the name “attachable” doesn’t really add any polymorphicness to the example—just obscures things.
This app is a really great idea. Keep going!
April 10th, 2007 at 08:57 AM
Yah, what Chad said. And can’t you just get rid of the loaduser and checkauth functions and change load_image to:
def load_image
@image = current_user.images.find(params[:id])
end
?
April 11th, 2007 at 06:30 AM
Hi, I get an error when I try a rake migrate:
(in /Users/Source/restfulauthrspec) rake aborted! no such file to load – spec/rake/spectask /Users/Source/restfulauthrspec/rakefile:10
April 11th, 2007 at 06:49 AM
You have to install Rspec first:
sudo gem install rspec
April 11th, 2007 at 07:58 AM
Tobi, could you please elaborate on this idea that with_scope might be deprecated?
I’m working on an implementation of my models right now that makes use of this. I find it to be a very elegant solution for when you want to limit say, posts.in_moderation. Why would this be removed if there is no alternative?
April 11th, 2007 at 08:54 AM
Ok, I see the deal. withscope will only be available within models for custom finders. In my case, I will probably be doing aliaschainmethod on the default finder so my withscope’s will apply to all #find’s.
Seems that the model is where this stuff belongs, not in around filters. Are resources an exception?
April 11th, 2007 at 04:59 PM
Seems that
Image.find(params[:id])
will raise ActiveRecord::RecordNotFound, in case there’s not such record/id in DB, so there’s no need to raise the exception explicitly in your load_image method ?