[rspec-users] [rails] An authorization question

Stephen Eley sfeley at gmail.com
Mon Mar 2 23:35:51 EST 2009

On Mon, Mar 2, 2009 at 5:16 PM, Zach Dennis <zach.dennis at gmail.com> wrote:
> Forgot to mention what we did do. We ended up with the following...
> def index
>  if user.has_role?("admin")
>    user.in_role("admin").invoices
>  elsif user.has_role?("associate")
>    user.in_role("associate").invoices
>  else
>    raise AccessDenied
>  end
> end

That seems sort of backwards to me.  These aren't the user's invoices,
right?  They're just invoices which the user happens to be allowed to
see?  Chaining it this way makes it look like the invoices *belong* to
the role, and seems put the user up front instead of the invoices.
You also have conditional branching with hardcoded values, making the
controller brittle, and some redundancy with the controller asking the
model for a value and then passing the value right back to the model.

Can a model have more than one role?  If it can, you have a problem
here because the 'if' will only ever *act* on one role.  If it can't,
life gets simple:

def index
  @invoices = Invoice.by_role(user)
rescue AccessDenied
  flash[:warning] = "Nope.  Sorry.  Nice try."
  redirect_to :back

[Invoice model]
def by_role(user)
  case user.role
  when "admin"
  when "associate"
    raise AccessDenied

...That could probably still be made more elegant.  I'm not a huge fan
of case statements, and I have in my head some idea that you could
have named scopes for each role and use "send" to pick the right
scope.  But that could be overdesigning it, and in any case I don't
really know what each role has to return in your business case.

The important takeaway here is that the Invoice is responsible for
figuring out what to return, based on user data passed to it at
runtime; the User doesn't have to have special logic to know how to
query every other model in the system.

Have Fun,
   Steve Eley (sfeley at gmail.com)
   ESCAPE POD - The Science Fiction Podcast Magazine

More information about the rspec-users mailing list