Pivotal Labs

Nick Kallen's blog



Access Control & Permissions in Rails

edit Posted by Nick Kallen on Thursday July 26, 2007 at 02:55AM

Access Control is a simple idea. We want company employees to be able to delete inappropriate content; but random Users cannot. Here I propose one way to implement Access Control that has the particular advantage of being very general, very concise, and unlikely to be violated. I call it RESTful Access Control.

Creating Multiple Models in One Action

edit Posted by Nick Kallen on Wednesday July 18, 2007 at 07:30PM

One of the issues in my previous post The Controller Action that sparked some interest is the handling of the creation of multiple Models in one Action. In this post I shall elaborate on this problem in some detail, first considering the cases where in constructing the Dependent Object no data are needed from the querystring/params, and secondly where such data are necessary (and where we have a complicated nested Form). Let's head right in to an example.

With No Extra Params to Worry About

Your site has Groups and Memberships. Our Business Rule is: when a user creates a Group, she should also be a Member of that Group. Following the Controller Formula, we know the solution in advance:

class GroupsController < ActionController::Base
  def create
    group = logged_in_user.groups.build(params[:group])
    raise SecurityTransgressionError.new unless logged_in_user.can_create?(group)
    if group.save
      ...
     end
  end
end

This leaves unresolved where to put our Business Rule...

The Controller Formula

edit Posted by Nick Kallen on Monday July 16, 2007 at 04:47PM

When I introduce a programmer to Rails I encourage them to read the article Skinny Controller, Fat Model. My only complaint about this article is that it applies the Skinny/Fat Pattern in a vague way, proceeding as if by intuition. I've found instead that there is a formulaic way to produce excellent Controller code--the Controller Formula

Skinny/Fat: Code Complexity vs. Abstraction Boundaries vs. The Formula

The Skinny/Fat pattern is typically stated in terms of Lines of Code. Your Controllers should have few Lines of Code; where there are many, move them to the Model. This rule has more exceptions than it has applications, so we can state the intent of the Pattern more precisely in terms of Abstraction Boundaries. Remove all Business Logic from your Controllers and put it in the model. Your Controllers are only responsible for mapping between URLs (including other HTTP Request data), coordinating with your Models and your Views, and channeling that back to an HTTP response. Along the way, Controllers may do Access Control, but little more. These instructions are precise, but following them requires intuition and subtle reasoning. The purpose of this post is to avoid subtle heuristics like Abstraction and Code Complexity. There is a Formula. Let's see an example that follows the Formula:

def create
  model = Model.new(params[:model])
  raise SecurityTransgressionError.new unless logged_in_user.can_update?(model)
  if model.save
    render ...
  else
    ...
  end
end

What's going on here? The Action channels user input to the model. It raises an Exception if the user lacks permission to perform this Action. Validation is performed by the model. Given the results, the Controller renders the appropriate Template to the HTTP Response.