yeah what is that

Jared Carroll

Now most of the Rails community is familiar with map.resources since it was officially released in Rails 1.2.3. But another method came with it that I’ve never used or seen anyone use. So I decided to investigate it.

Looking at the doc for ActionController::Resources#resource it says

No default index, new, or create routes are created for the singleton resource controller.

OK, so it looks like I shouldn’t be creating these things with HTML forms. My first impression was that #resource was for one-to-one associations but that doesn’t seem to be the case.

Some further reading says #resource only gives you #new and #edit named routes.

OK, so it looks like I can view and edit these things and not delete them.

Here’s what I think they should be used for.

Say we have users in our system. And users have some attributes that are central (and are usually required) to a user:

  • email
  • password
  • name

As well as several attributes that seem to be related to their profile (and are usually optional):

  • age
  • date_of_birth
  • bio

Now you could say we have 2 objects here:

  • User
  • Profile

And a User has_one Profile. But lets keep it simple and instead put everything in the users table.

A client is then going to ask can we have 2 separate pages for viewing/editing our basic user information and our profile information?.

Our first implementation might look like this:

class UsersController < ApplicationController

  def new
  end

  def create
  end

  def show
  end

  def edit
  end

  def update
  end

  def profile
  end

  def edit_profile
  end

end

Look at those 2 ugly actions:

  • profile
  • edit_profile

Lets move them into a separate profiles controller so we can stay with the CRUD action naming convention.

class ProfilesController < ApplicationController

  def show
  end

  def edit
  end

end

We don’t need an #update action in our ProfilesController because the #edit form will POST to UsersController#update because it is editing a User anyway.

Here’s our routes file:

In config/routes.rb:

ActionController::Routing::Routes.draw do |map|

  map.resources :users do |user|
    user.resource :profile
  end

end

That #resource gives us:

/users/1/profile
/users/1/profile;edit

And some named routes:

profile_path
profile_url
edit_profile_path
edit_profile_url

Now we have actions whos names don’t stray from the basic CRUD naming conventions and also get some free named routes from Rails.

Has anyone else used #resource? And what for?