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:
- 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?