Pivotal Labs

Main menu

Skip to primary content
Skip to secondary content
  • About
  • Case Studies
  • Team
    • Executives
    • Locations
      • San Francisco (HQ)
      • Boston
      • Boulder
      • Denver
      • London
      • Los Angeles
      • New York
  • Community
    • Blogs
    • Tech Talks
    • Events
  • Careers
    • Lifestyle
    • Principles & Practices
    • Benefits
    • FAQ
    • Apply
  • Contact
    • Press Room
    • Press Releases
    • In The News
    • Press Kit
  • All
  • Labs
  • Standup
  • Tracker

Lovely Demeter, Meter Maid

Alex Chaffee
Sunday, August 5, 2007

Wes and Parker pointed us to this article:

Misunderstanding the Law of Demeter by Dan Manges

which is a very nice discussion of the “law” (actually just a suggestion, but a very strong one) that encourages your objects, like small children, not to talk to strangers. Some people seem uneasy with the LoD since it requires them to refactor their objects to have proxy methods all over them. Instead of Paperboy calling customer.wallet.cash you have to put an extra method on Customer — either cash (attribute delegation — check out Forwardable in Rails btw) or pay (behavior delegation). But these proxy methods are not clutter, they’re the essence of encapsulation. Do not fear encapsulation. Fear is the mind killer.

Anyway, Dan does a great job explaining this concept, until the very end of the article, when he totally chickens out.

Let’s say we’re developing a Rails view to display order information, and this should include details on the customer. We might write the view like this:

<%= @order.customer.name %>

…Our view now becomes:

<%= @order.customer_name %>

We’ve traded a dot for an underscore. And thinking about this further, why should an order have a customer_name? We’re working with objects, an order should have a customer who has a name. Adding these attribute delegations also decreases maintainability.

The crux of this is that webpage views aren’t domain objects and can’t adhere to the Law of Demeter. Clearly from the examples of behavior delegation the Law of Demeter leads to cleaner code. However, when rendering a view, it’s natural and
expected that the view needs to branch out into the domain model.

This is dead wrong. Ading delegation — for getters, at least — increases
maintainability, and especially mockability. It makes perfect sense
for an order to “have” a customer name — that is, respond to a
message querying it for its customer’s name — since now the order can
do things like decorate the customer’s name, or fake one up if there’s
no customer object set on the order. And if the interface of Customer
changes then none of the clients (including tests) of Order need to
change at all.

[ Invoice (view) ] -> [ Order ] -> [ Customer ]

The crux of this is that webpage views aren’t domain objects and can’t
adhere to the Law of Demeter.

Wow again. This is circular reasoning (the “begging the question”
fallacy). Why aren’t webpage views domain objects? Why did Rails make the
bizarre decision to make one of the MVC Holy Trinity be just plain text files,
and to share all instance variables (ugh) with the controller? Why can’t views
adhere to reasonable object-oriented semantics and support
encapsulation, interface-based design, etc. etc.?

See my post “Life
Without Getters”
for an alternate vision… Or (thanks Wes) the Presenter Pattern…

…but even without going down those roads, the LoD provides a great way
of keeping views isolated from a tangled nest of model objects, all
pointing to each other. I try to make my views connected to a small
set of objects — often just one — and to make sure each of those objects’
public APIs exposes everything the view needs.

Clearly from the examples of behavior
delegation the Law of Demeter leads to cleaner code. However, when rendering
a view, it’s natural and expected that the view needs to branch out into the
domain model. Also, anytime something in a view dictates code in models,
take caution. Models should define business logic and be able to stand alone
from views.

More FUD.
A view is a perfectly valid client of a model object, and if
some of its logic makes more sense encapsulated in the model — say,
as a "display_name" property on a Car object which concatenates make,
model, and year — then that’s where it should go. Put the behavior
with the data, tell don’t ask, and don’t peep into your neighbor’s
windows.

Edit: We’re famous! This thread is referenced on the Wikipedia Law of Demeter page.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Access Control & Permissions in Rails

Pivotal Labs
Thursday, July 26, 2007

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.

What is RESTful Access Control?

When we model RESTfully the Application Interface (i.e., the HTTP interface), we construe Resources as responding to a simple set of Verbs: Get, Put, Post, Delete. To the extent that our entire application is designed this way, we can Control all Access to our Application with perfect granularity: as being a set of Permissions to perform these four Verbs on a corresponding Resource. Let’s start with an example.

Suppose a User can add Members to a Group. How do we determine if this or that User can create a Membership? This logic doesn’t belong in the controller — call me a prig, but Business Logic belongs in the Model. Anything else is unbecoming. Therefore, we have a Controller like:

class MembershipsController < ApplicationController
  before_filter :load_group

  def create
    membership = @group.memberships.build(params[:membership])
    raise SecurityTransgression unless current_user.can_create?(membership)
    ...
  end

  def load_group
    @group = Group.find(params[:group_id])
  end
end

Let’s implement the can_create? method. Despite the above Formulaic code, the User Class isn’t really the proper place for the Logic: different kinds of resources are likely to have different rules. Thus, we implement the Logic in the Model being created:

class Membership < ActiveRecord::Base
  def can_be_created_by?(user)
    ...
  end
end

I call the above “the Passive Voice.” I prefer, for various reasons, to use the “Active Voice”, and therefore we implement a simple Proxy in the User Class:

class User < ActiveRecord::Base
  def can_create?(resource)
    resource.can_be_created_by?(self)
  end
end

Of course, this “Active Voice” implementation requires that we follow the Null Object Pattern for Users who are not Logged In, otherwise we’ll produce Errors when we ask if a Logged Out User has Permission to do something:

class AnonymousUser < User
  ...
end

Why we Always Create An Instance Before Checking Permission

In our Controller Action above, we first build an instance of a Model in memory, then ask for Permission.

membership = @group.memberships.build(params[:membership])
raise SecurityTransgression unless current_user.can_create?(membership)

But why even create the Model in memory it shall not be persisted? Well, for some advanced Access Control Rules, we need all of the data available to an Instance in order to proceed. Suppose, for example, that only the Owner of a Group can create Memberships. The simplest way to enforce this rule is to reference the Group Owner in the can_be_created_by? method:

class Membership
  belongs_to :group

  def can_be_created_by?(user)
    group.owner == user
  end
end

Similarly, can_be_destroyed_by?, can_be_updated_by?, and can_be_read_by? all must be instance methods. This provides the maximum flexibility and a consistent Interface.

This is a robust Pattern for Access Control. It extends brilliantly to User Roles:

def can_be_destroyed_by?(user)
  user.admin? or ...
end

Even a per-user Access Control scheme where we grant individual Users permission to manipulate individual objects can elegantly fit in. Consider something like the following:

class Permission
  belongs_to :user
  belongs_to :resource, :polymorphic => true
end

class CreatePermission < Permission
end

class Membership
  has_many :create_permissions, :as => :resource

  def can_be_created_by?(user)
    create_permissions.find_by_user_id(user)
  end
end

Handling Access Control in the Views

Access Control has View consequences as well. For example, we shouldn’t show a destroy button if the User lacks permission to perform that Action. Given the above implementation, this is simple enough:

 <%= link_to_unless current_user.can_destroy?(resource), 'destroy', ... %>

Why Exceptions?

Above, I’ve proposed using Exceptions to handle Security Transgressions. (At Pivotal, we call these Exceptions SecurityTransgressions because it has a more romantic air than the banal AccessDenied). Normally, these Transgressions cannot happen: in your Templates you will not even display links to modify an object if the User lacks Permission. So Transgressions occur only when a User is fiddling about with nefarious intent. So we can handle misbehavior consistently across the site, by (for example) rendering a HTTP 403 Forbidden Response. Exceptions are a neat way to do this, because Rails gives us a systematic way to handle exceptions with rescue_action:

 class SecurityTransgression < StandardError; end

 def create
   raise SecurityTransgression unless ...
 end

class ApplicationController < ActionController::Base
  def rescue_action(e)
    case e
    when SecurityTransgression
      head :forbidden
    end
  end
end

Ensuring Programmers Remember to do Access Control And How to Avoid Over-Engineering

The biggest danger with Access Control rules is the possibility that a careless Programmer might forget to implement them. Having a consistent, terse pattern for Access Control goes some way towards mitigating this problem. When all Access Control is as simple as adding a can_create? check to your Actions, Access Control is unlikely to be overlooked.

The Second biggest danger in Access Control is over-engineering. Suppose we want to enforce Access Control logic. Rails gives us some tools to do this. Well, Rails gives us just enough rope to hang ourselves. There are some serious disadvantages to the approach I am going to propose now, but we’ll get to that shortly.

Rails has something called an Around Filter. An Around Filter, like a Before and After Filter, is a Filter applied to every Action. But this Around filter is like the Heavenly Union of the Before and After Filters: both great tasting and less filling, it can do work before and after invoking the Action.

class ApplicationController
  around_filter :ensure_permission_to_create, :only => :create

  def ensure_permission_to_create
    class_name = ModelsController.to_s.demodulize.gsub(/Controller$/,'').singularize
param_name = class_name.downcase
    instance_variable_name = "@#{class_name.downcase}"

    instance_variable_set instance_variable_name, class_name.constantize.new(params[param_name])
    if current_user.can_create?(instance_variable_get instance_variable_name)
      yield # the create acction is invoked here.
    else
      head :forbidden
    end
  end
end

Whew. In the above implementation, control is yielded to the Action only if the User has permission. The instance of the Model is also built for us automatically; so, our Formulaic create Action becomes:

def create
  if @model.save
    ...
  end
end

Very DRY, But this is, again, just enough rope to hang ourselves with. Our Controllers need to be named exactly right, our parameters without an inconsistency, and so forth. This is not a problem in the World of Forms, but in Reality it may require some coding contortions. The tricky metaprogramming and impertinent assumptions in ensure_permision... only get nastier when we want to make a Nested Resource, and build our Model using a proxy (as in the previous example: @group.memberships.build(params([:membership])). Finally, where we have Controllers that do not map directly to ActiveRecords, we would need to introduce a Model layer that responded to the Interface defined in ensure_permission... We often want to do this, but not always. Being forced to might suck. So I offer this design strategy with much caution.

The Exception based approach, while a bit more verbose, is battle-tested and works in Practice. In any case, pushing the logic to the Model with can_be_created_by? will certainly work, regardless of whether you take the Around Filter approach or the Exception-Based one.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Nathan Wilmes

Til the End of Time (or Time.now)

Nathan Wilmes
Wednesday, July 18, 2007

Sooner or later, every test-driven developer discovers that they need a superpower – the power to control time. Let’s say you’re working on a scheduling system. You’re going to want to write tests that say, “Assume that it’s 2PM on January 3rd and this user does THIS. What happens as a result? What happens at 4PM on January 3rd as a result?”

One of the joys of writing in Rails is the sheer power you have to change your application universe at almost any level you choose. As a result, we’ve come up with a variety of ways to solve this problem. As it turns out, with great power comes great responsibility. (I’m not sure why I’m going all comic book right now, but let’s run with it).

Stubbing Time

One of the cooler features of the latest generation of mocking frameworks like FlexMock and Mocha is the ability to stub any method you choose and replace its functionality with a new one of your choosing.. and then the framework will clean up after you when the test is over!

This leads us to some intriguing possibilities such as the following:

def test_party
  Time.stubs(:now).returns(Time.local(1999, 'Jan', 1))
  people(:nathan).party
  assert people(:nathan).very_drunk?
end

and for the duration of the test, Rails will decide that it needs to party like it’s 1999. Sounds great, right?

Well, there’s just a teeny catch.

Let’s try benchmarking the test_party method.

Benchmark.measure do |b|
  ... test_party
end

And you’ll discover that this test takes -2000000 seconds to run!

Here’s another problem area:

def test_partying_in_selenium
  Time.stubs (:now).returns(Time.local(1999, 'Jan', 1))
  click "link=Party!"
  wait_for {get_text("id=sobriety") == "drunk"}
end

The issue with this method is that the wait_for method relies on Time.now to time out.. and Time has now been mocked out for the duration of the test. So we end up with a Selenium test that takes forever.

So doing a mass Time.now stub will work, but stubs out the test framework along with your application. Not a great solution.

How about this?

A Time wrapper for your application

The idea here is that we define a time wrapper class that we use for our application.. let’s call it Clock. The idea of the Clock object is that the application refers to the Clock every time it needs to know what time it is. Clock would have a very similar API to Time.. we can use Clock.now instead of Time.now, and switching over is as simple as a global search and replace.

Clock.now does exactly the same thing as Time.now… except when you’re running tests. When you run tests, you suddenly get access to clock-controlling methods, and can change what the application’s sense of ‘now’ is for the duration of a test.

Here’s a simple implementation of Clock:

in lib/clock.rb:

class Clock
  def self.now
     Time.now
  end
end

in mocks/test/lib/clock.rb:

class Clock
  def self.now
     @@now ||= Time.now
  end

  def self.now=(new_time)
     @@now = new_time
  end
end

To finish off, here’s example test code that uses this:

def test_party
  Clock.now = Time.local(1999, 'Jan', 1)
  people(:nathan).party
  assert people(:nathan).very_drunk?
end

def teardown
  Clock.now = Time.now
end

Some other benefits to this approach is that you have a handy place to add fancier setters to Clock. You can use methods like Clock.tick(2.hours), Clock.advance_to_midnight, et cetera. The actual implementations of these methods would be very simple, and I’ll leave them as an exercise for the reader who wants to use them.

Here’s some issues you’ll run into, though:

  • The implementation I wrote above doesn’t automatically tear down the Clock time override after your test is done. As a result, you’ll have to do this teardown yourself. If you don’t, later tests will think that Clock.now is whatever the previous tests say it is, and you may end up with fragile interactions between tests as a result. Very bad.
  • Rails has many lower-level methods that use Time.now directly, and these methods don’t easily switch over to Clock.now. Among the more interesting ones are the created_at and updated_at methods, and constructs like 3.days.from_now and 5.hours.ago. So, you’d need workarounds to test these methods.

Here’s a case that would work:

def Clock.ago(duration)
  Clock.now - duration
end

def Clock.from_now(duration)
  Clock.now + duration
end

Using stubs rather than a separate mock clock class

Why do we need to create an ‘Clock.now=XXX’ method, anyways? If we use stubs to override what AppTime.now returns, we can let the test framework clean up after itself when the test is complete. In addition, we can drop the mock definition entirely.. a very good thing indeed.

So in this universe, we’d end up with something like this:

Here’s a simple implementation of Clock:

in lib/clock.rb:

class Clock
  def self.now
     Time.now
  end
end

in mocks/test/lib/clock.rb: nothing!! this file doesn’t exist!

Test code:

def test_party
  Clock.stubs(:now).returns(Time.local(1999, 'Jan', 1))
  people(:nathan).party
  assert people(:nathan).very_drunk?
end

This approach has the advantage of reducing the number of ‘special’ test-only objects you have, and working more closely with the objects your application uses. The disadvantage is that you can no longer add lots of test-only helper functions to describe how you’re playing with the clock more clearly.. at least, not in the ‘Clock’ object.

Can we change Rails to use a settable clock?

The Rails code refers to Time.now in many, many places (just try a global search of your gems directory, and you’ll see what I mean.) At this point, the hooks are not in convenient places to allow for a settable clock.. you would have to copy entire method signatures and tweak some Time.now references, which ties your changes to a particular Rails install and creates unfortunate forks in your code. So, I would say that the answer for now is, sadly, “No”.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Creating Multiple Models in One Action

Pivotal Labs
Wednesday, July 18, 2007

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…

Let’s just put it in the Model as a before_create:

class Group < ActiveRecord::Base
  belongs_to :creator, :class_name => 'User'
  has_many :memberships
  has_many :members, :through => :memberships

  before_create :create_first_member

  private
  def create_first_member
    memberships.build(:member => creator)
  end
end

Building the Membership as a before_create relies on the fact that objects built in a Proxy will be cascaded (i.e., saved) on creation.

Some Extra Params to Worry About

A more complicated example is where we have a Form that prompts the User for data for the creation of two Models, one Dependent upon the other. Let’s use the example where our Model is a Cyclops and the Dependent Model is an Eyeball. First we need a new Action:

def new
  @cyclops = Cyclops.new
end

Pretty Skinny, eh? Very Formulaic too. The corresponding View will look something like this:

<% form_for :cyclops do |c| %>
  ...
  <% fields_for 'cyclops[eyeball_attributes]', @cyclops.eyeball do |e| %>
    ...
  <% end %>
<% end %>

When the User submits this form, params come into our create Action looking like this:

{
  'cyclops' => {
    'name' => 'Polyphemus',
    'eyeball_attributes' => {'color' => 'grey'}
  }
}

So what should the create Action look like? Well, we don’t have to think about it, because we’re following the Controller Formula:

def create
  cyclops = Cyclops.new(params[:cyclops])
  ...
  if cyclops.save
    ...
  end
end

Two things now need to be implemented in the model. First, @cyclops.eyeball should not be nil even if the Cyclops is brand new. This is because we assume an Eyeball exists when we draw the new Form. A simple way of accomplishing this is the override the getter for eyeball so that it will build an eyeball if none exists:

class Cyclops < ...
  has_one :eyeball

  def eyeball
     @eyeball || build_eyeball
  end
end

This still leaves unresolved how to deal with setting the Dependent Model, the Eyeball. Given the way we drew the form above, we need merely implement eyeball_attributes=:

class Cyclops < ...
  ...
  def eyeball_attributes=(attrs)
      eyeball.attributes = attrs
  end
end

The eyeball_attribues= method will get called automatically when the create action passes in params[:cyclops] to the Cyclops initializer. (I wish we didn’t have to call this Attribute eyeball_attributes, but calling it just eyeball would require too much fancy footwork for my taste)

At this point, the only issue outstanding is how to deal with Validation. An invalid Dependent Model (which cannot be saved) will not make the Parent Model invalid by default when has_one is used (but it will validate by default when using has_many–there’s your Principle of Least Surprise for ya!). So it’s easy to imagine a scenario where the User inputs bad data for the Eyeball, good data for the Cyclops, and therefore Rails would save the Cyclops but not the Eyeball, and we’d have a sightless Cyclops with nary an error in sight. The only logical thing to do is add the following Business Rule: a Cyclops is invalid on creation if its Eyeball is invalid. This is simple enough:

class Cyclops < ...
  validates_associated :eyeball, :on => :create
end

I love Rails.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

The Controller Formula

Pivotal Labs
Monday, July 16, 2007

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.

Note a few things about this example. All of the access control rules (i.e., Business Logic) are specified in the Model (in this case, in the can_update? method on User). All data validation rules (again, Business Logic) are specified in the Model. There are three benefits to this approach: 1) the Logic in the Model is easier to test as it’s isolated. 2) Our Abstraction Boundaries are respected. 3) Our Controller is brief, i.e. Skinny. The resulting Controller some call anorexic. But I think it is like a conductor: all of the rhythm and melody comes from the players but the conductor keeps the whole orchestra in sync. But metaphors, testing strategies, and hoity-toity talk of Abstraction Boundaries aside, this example is good code because it follows the Formula.

Let’s consider a more sophisticated example.

Transactions and Compound Creations

Suppose that when creating a model of type Model, we always also want to create another type, DependentModel. We might be tempted to write something like:

def create
    model = Model.new(params[:model])
    dependent_model = model.dependents.build(params[:dependent_model])
    if model.save ...
end

Two Models created in one Action! This looks nothing like the Formula. Just push the creation of the DependentModel into Model and we have:

def create
    model = Model.new(params[:model])
    if model.save ...
end

Voila! The Formula.

How assigns fit into the Formula

Let’s consider another Action, one of the non-side-effecting persuasion.

def edit
  model = Model.find(params[:id])
  raise SecurityTransgressionError.new unless logged_in_user.can_update?(model)
  @colors =  Color.find :all
end

We can see the same access control pattern as in the previous example, but absent is any input validation as the user is not modifying anything. Something new here is the assignment of @colors. Typically, when we are displaying something to the user (in this case, an edit form), we will be listing various data; in this case, these data are the possible colors a model can be. Years ago, DHH issued a bull stating that “Thou Shalt Not Call Find in Thine Template”. This commandment is not without its problems, but that’s an issue for another blog post. This loading of the data is part of the Formula.

Push all your Find logic into the Model

Let’s take this edit action one step further. Suppose Users of type Admin can assign a certain set of colors to a Model, but other Users can select from a smaller set. Let’s rewrite edit to support these new business rules:

def edit
  model = Model.find(params[:id])
  raise SecurityTransgressionError.new unless logged_in_user.can_update?(model)
  @colors = logged_in_user.admin?? Color.fabulous_colors : Color.drab_colors
end

Something has gone wrong here: we’ve put Business Logic in the Controller, ack! But rather than appeal to some ethereal Abstraction Boundaries, just notice that it doesn’t follow the formula exemplified above–it’s got an extra conditional in the assignment of @colors. Let’s redesign this a bit, just aiming to adhere to the Formula:

def edit
  model = Model.find(params[:id])
  raise SecurityTransgressionError.new unless logged_in_user.can_update?(model)
  @colors = Color.find_by_user_role(logged_in_user.role)
end

Much better. We’ve put the rules of determining which color set to select based into the Model, and we have no more Control Flow than our original definition of edit above. This is Skinny as can be. We haven’t violated any Abstraction Boundaries. The color logic is easier to Unit Test. But these ends can be accomplished on auto-pilot just by following the Formula.

Let’s complexify this example one step further.

Conditional Logic Based on Session Data or other HTTP Request Data

def edit
  ...
  if logged_in_user.admin?
    render :action => 'edit_admin'
  else
    render :action => 'edit_normal'
  end
end

This is not Skinny at all. But, rendering different templates based on the User role is not Business Logic per-se. Rather, it is logic concerning what information is directed to the HTTP response. This properly belongs in the Controller. We could push this into the model:

render :action => model.edit_action_for_user_role(logged_in_user.role)

But this would make the model know about the View, which is unethical. We could use something like the Visitor Pattern to maintain abstraction boundaries but that is ridiculous overkill here. We could put our Fat edit action on a diet by breaking the two conditions into different edit actions on different Controllers. This approach is, perhaps, more RESTful in spirit:

class AdminModelsController
  ...
end

class UserModelsController
  ...
end

All of these concerns: violating Abstraction Boundaries, Lines of Code, the complexity of the Visitor Pattern, whether one approach is more RESTful than another… in the end it’s just a judgement-call between unappealing alternatives, and no two programmers will make the same choice, and I on any given day will choose variously. So just follow the Formula. Break it out into two controllers so we can have two edit actions, each well behaved.

The Full Formula

Let’s look at a ‘grammar’ for the Formula, and we’ll soon be done.

def non_side_effecting_action
  model = Model.find(params[:id])
  raise SecurityTransgressionError.new unless logged_in_user.can_action?(model)
  @assign1 = Foo.find :all
  ...
  @assignN = Bar.find_for_user(logged_in_user)
end

def side_effecting_action
  model = Model.new(params[:model])
  # or: model = Model.find(params[:id]); model.attributes = params[:model]
  raise SecurityTransgressionError.new unless logged_in_user.can_action?(model)
  if model.save
    @assign1 = Foo.find :all
    ...
    @assignN = Bar.find_for_user(logged_in_user)
    render :action => ... # or redirect_to ...
  else
    ...
  end
end

Some details are left out here… And obviously, there will be cases where the Formula needs to be elaborated. There might even be a few cases where the Formula needs to be abandoned. But I think you’ll find it useful most of the time.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Rails, Slashdotted: no problem

Pivotal Labs
Wednesday, June 27, 2007

By Steve Conover and Brian Takita

Peer-to-Patent, one of Pivotal Labs’ clients, got Slashdotted last week, and we had no trouble handling the load. The site was just as responsive as it always is, and we didn’t come close to having a scale problem.

Moral of the story: the technology for serving static web pages is old, boring, and extremely scalable. If you have the type of site that can be page-cached, do so aggressively, starting with the front page and any pages likely to be linked to. We got a huge payoff for the engineering time that we invested in our page-caching strategy.

Highlights:

  • We moved away from Rails page-caching and developed our own “holeless cache”, which uses a symlink trick (see below) to instantly and “holelessly” switch to a new version of a cached page. (The cache “hole” is the time between the expiration or purge of a cached page and the time when it’s regenerated. The danger is that in that time your Mongrels can be saturated with requests – something we proved to ourselves could easily happen.)
  • Here’s our symlink trick, using the front page as an example:

    1. Have index.html point to index.html.current
    2. If (index.html.current is >= 20 minutes old)
      1. Copy index.html.current to index.html.old
      2. Point index.html to index.html.old
      3. Rewrite index.html.current by asking Rails for the page (using the process method)
      4. Repoint index.html back at index.html.current
    3. Repeat step 2 every minute using a cron job.
  • For cache expiration that’s model-based, we make a call from the model observer class to our holeless cache routine, instead of using Rails cache sweepers. So, instead of just deleting the cached page we regenerate it in place.

  • It was important to write tests that proved that the HTML we generated for cached pages looked exactly the same in different “modes” (user logged in vs not, for example). This forced us to push modal decision logic out of Markaby templates and into JavaScript, meaning that view-oriented Rspec tests asserting modal differences became useless. We rewrote them as Selenium tests.

  • Performance/load testing: we tried several tools and approaches and found that a simple Ruby script that launches wget requests (that write to /dev/null) in many separate threads worked best for us.

  • We send down exactly one .js and one .css file. If you are sending down more than one of each of these to the browser, you have a performance problem. Fix it with asset packager.

Update: one clarification about the cron job: we deploy this “automatically” using capistrano.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Rails Filter Parameter Logging

Alex Chaffee
Wednesday, May 30, 2007

Q: How do you keep passwords from appearing in plain text in your Rails log file?

A: Filter Parameter Logging

filter_parameter_logging
=> Does nothing, just slows the logging process down

filter_parameter_logging :password
=> replaces the value to all keys matching /password/i with "[FILTERED]"

filter_parameter_logging :foo, "bar"
=> replaces the value to all keys matching /foo|bar/i with "[FILTERED]"

filter_parameter_logging { |k,v| v.reverse! if k =~ /secret/i }
=> reverses the value to all keys matching /secret/i

filter_parameter_logging(:foo, "bar") { |k,v| v.reverse! if k =~ /secret/i }
=> reverses the value to all keys matching /secret/i, and
   replaces the value to all keys matching /foo|bar/i with "[FILTERED]"

(Note that :password matches password_confirm too.)

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

REST: Theory to practice

Pivotal Labs
Thursday, May 24, 2007

REST. What is it, and how can it be used to design better web applications?

A presentation at RailsConf did me a great service by first pointing out all the things REST is not. It isn’t CRUD. It isn’t pretty URLs. It is neither a protocol nor an architecture, but it can play a role in your implementation of all of the above. REST itself though, is less concrete than all of that. It is a theoretical framework, a way of thinking about designing distributed software systems. For me, the first step in absorbing its principles is to forget about the database and focus on the fundamentals. This article will start there, then drill down to show how these ideas can help organize the development of your Rails applications.

Noon: Rest From Work (After Millet) by Van Gogh

(Noon: Rest From Work (After Millet) by Vincent Van Gogh)

REST encourages a focus on resources. A resource is anything that can be named, and your system can have as many resources and corresponding names as you want. Conversely, there is a limited set of operations defined on those resources. Unlike objects in object-oriented programming languages, which support very diverse, rich interfaces, resources in a RESTful system are relatively uniform. So how can a sophisticated API be developed if REST requires a fixed and limited number of operations that resources can support? The answer: add more resources!

Lets play with an example. Say I’m writing a web application that has a collection of shapes that can be moved to new locations. In an object oriented program, I might have a move method defined on each shape, but in this RESTful API, I have assigned consistent semantics to a limited set of operations supported by the HTTP protocol. I can show GET, create POST, update PUT, and destroy DELETE my resources. Nowhere in the HTTP specification is the a MOVESHAPE method defined. A naiive approach to remedying this limitation is to shoehorn this operation into the protocol by abusing URLs.

http://againstgrain.com/shapes/move/1

I call this abuse because URL stands for uniform resource locator, and it’s very hard to see this imperative-style command encoding as much of a resource. This is an API decision that fights the nature of the protocol it uses. How can the API go with the flow?

There are many potential solutions. Let me outline two, the first very simple, the second more sophisticated.

The first solution is to recognize that a move operation is just a change to the location of an object. If we expose this location as a resource and allow it to be updated, we’ll implement movement in a natural way without contorting URLs to name things that aren’t actually resources:

So we combine one of the four standard operations:
Update, represented by an HTTP PUT

With a resource:
http://withgrain.com/shapes/1/location

Updating the location of the shape will naturally equate to moving it.

But what if we want the movement to be relative to the objects current position, so that the client can say that they want a shape to move 5 pixels up and 10 pixels to the right without needing to know the objects current position or do any computation? To solve that problem, we apply a technique I learned doing computational semantics: reification.

Reification means that we give solid form or objecthood to something formerly fleeting or ephemeral. Anything can be reified. The fact that I am named Nathan Sobo can be thought of as my NathanSoboness, which is an (albeit abstract) conceptual object. Here we’ll apply the technique in a more conservative fashion, and say that shapes are associated with a history of movements. This movement history is a collection, which is itself a resource.

http://withgrain.com/shapes/1/relative_movements

Now say we want to move the shape. We combine the above resource locator with one of our standard operations, create, implemented as an HTTP POST. By posting a new movement to a shapes history, we cause the shape to move.

Now we’re working with HTTP rather than around it.

So how does this transfer to the design of Rails applications? Embracing resource oriented application development means you’ll be writing more controllers with fewer, more consistent methods. Lets work through a potential implementation of the shape API in Rails. It will all start in the routes file, with map.resources…

Lets say we want to expose both the relative and absolute means of moving a shape. First we’ll start with a shapes resource.

map.resources :shapes

This represents the collection of all shapes in our system. It assumes the existince of a corresponding ShapesController and will set up a series of routes and url-generating methods to help reference the actions therein. Note the controller and its standard complement of methods below.

class ShapesController < ActionController::Base
  def index
  end

  def show
  end

  def create
  end

  def edit
  end

  def update
  end

  def destroy
  end
end

But with map.resources, the actions on the controller do not play a critical role in the url. They merely name the operations to which a given pairing of HTTP request method and URL will map. GETting /shapes will execute index. POSTing to /shapes will execute create. GETting /shapes/:id will execute show. PUTting to /shapes/:id will execute update, and DELETEing /shapes/:id will execute destroy. So even though there are 5 actions, there are really only two url patterns, one referencing the resource that is the collection of all shapes, and another referencing resources that are members of that collection. We can reference these URLs with automatically defined methods:

shapes_url ---> /shapes
shape_url(@square) or shape_url(@square.id) ---> /shapes/1

By pairing these with the correct HTTP method, we can access every operation we need.

Now lets add relative movement:

map.resources :shapes do |shape|
  shape.resources :relative_movements, :name_prefix => 'shape_'
end

class RelativeMovementController < ActionController::Base
  ...
end

This again assumes the existence of a RelativeMovementController with all of the standard methods defined on it. Except the resources supported by this controller are nested within shape resources, so the URL patterns look like this:

/shapes/1/relative_movements
/shapes/1/relative_movements/4

Because of the :name_prefix supplied (which will no longer be needed at some release of Rails in the future), we can refer to these URLs with helper methods that look like this:

shape_relative_movements_url(@triangle) ---> /shapes/1/relative_movements
shape_relative_movement_url(@triangle, 4) ---> /shapes/1/relative_movements/4

All of the same rules about HTTP method choice allow access to the RelativeMovementController‘s actions.

Now a cool twist: Singleton resources. Lets add the nested position resource to shapes.

map.resources :shapes do |shape|
  shape.resources :relative_movements, :name_prefix => 'shape_'
  shape.resource :position, :name_prefix => 'shape_'
end

And a corresponding controller, this time with a different complement of methods:

class PositionController < ActionController::Base
  def show
  end

  def edit
  end

  def update
  end
end

Because position is a singleton resource nested inside of shape, this controller is designed to deal with a single resource rather than a collection of them, so there is no need for an index action. The HTTP verb / URL combination mappings are also different. So PUTting to /shapes/1/position will invoke the update action.

None of these changes are Earth-shattering, but the simple act of focusing on resources is a force that will organize your application. Rather than growing a hodgepodge of actions on ever fattening controllers, you’ll instead create a greater number of controllers that are more circumscribed in their responsibilities.

What does this say about your model? Not much. I used to think that it was important to have a controller for every model object, and I no longer do. Controllers are responsible for supporting the exposure of resources to a remote API. This collection of resources is, in a sense, your remote client’s model. Whether your resources map precisely onto your underlying data model is your business. For example, you might expose resources that have no direct correspondence in the model layer. Or you might have model objects that you don’t choose to expose as resources.

But regardless, REST finally provides an organizing principle for the controller layer. Even if you don’t plan on exposing a RESTful API as a service, thinking in terms of resources will help you build more consistent applications and help you make fewer decisions.

I realize that this article has by no means covered every aspect of REST, but I hope it fills a gap that I felt as I was learning all of this.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Rails Conference Links

Alex Chaffee
Monday, May 21, 2007

(Blabbers who were at the conference, feel free to add your links to this post.)

  • Alex’s RailsConf2007 Flickr set
  • railsconf2007 Flickr tag (notice all the band pix :-) )
  • Parker’s Flickr Set
  • Martin Fowler’s bliki post on RailsConf
  • Tim Bray on the band
  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Beer Night PDX

Alex Chaffee
Saturday, May 19, 2007

front
back

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Topics

  • agile (780)
  • rails (113)
  • testing (88)
  • ruby (83)
  • ruby on rails (70)
  • jobs (62)
  • javascript (55)
  • techtalk (44)
  • rspec (38)
  • ironblogger (32)
  • productivity (30)
  • activerecord (29)
  • gogaruco (29)
  • git (28)
  • nyc (27)
  • rubymine (26)
  • bloggerdome (23)
  • mobile (22)
  • process (21)
  • pivotal tracker (20)
  • cucumber (20)
  • jasmine (19)
  • design (18)
  • ios (18)
  • webos (17)
  • objective-c (17)
  • android (16)
  • palm (16)
  • "soft" ware (16)
  • fun (15)
  • tracker ecosystem (15)
  • ci (15)
  • cedar (15)
  • rails3 (14)
  • performance (14)
  • bdd (14)
  • gem (13)
  • css (13)
  • tdd (13)
  • selenium (12)
  • goruco (12)
  • bundler (12)
  • meetup (11)
  • railsconf (11)
  • nyc-standup (11)
  • capybara (10)
  • mac (10)
  • mojo (10)
  • chef (10)
  • api (10)
Subscribe to ruby on rails Feed
  1. ←
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. 6
  8. 7
  9. →
  • About
  • Case Studies
  • Team
  • Community
  • Careers
  • Contact
  • Labs
  • Events

Contact Us

contact@pivotallabs.com
+1 415-77-PIVOT
TwitterLinkedInFacebook

Pivotal Tracker

Tracker is the award-winning agile project management tool that enables real-time collaboration around a shared, prioritized backlog.
Visit pivotaltracker.com >