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”

  1. Tammer Saleh Says:

    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.

  2. tobi Says:

    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.

  3. protocool Says:

    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

  4. Pius Says:

    Hey man, really nice work – will help a lot of people learn and use best practices.

  5. Chad Fowler Says:

    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!

  6. Scott Becker Says:

    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

    ?

  7. Bruno Says:

    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

  8. thom Says:

    You have to install Rspec first:

    sudo gem install rspec

  9. Chad Burt Says:

    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?

  10. Chad Burt Says:

    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?

  11. gmarik Says:

    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 ?

Sorry, comments are closed for this article.