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?