lost password?

home
•  reviewramp
•  rails +
•  javascript
•  webdev
•  django
•  xaraya
•  xamp
•  musings

rss
Tag this page
   

» Blogs that link here
last modified: Dec 16, 2008
(first posted: Dec 16, 2008)
(1461 Reads)
Permalink

Oh my, my, my

A technique for handling routes to resources that the current user owns.

I've been struggling with how to manage resources that are owned by the current logged in user. The conventional way is to scope your finds by the current_user to ensure he's not getting someone elses stuff, e.g.

record = current_user.things.find( :first )

Or, a while back I introduced a pattern for pushing this into the model when its a has_many association (see has_one_of _many ), so you could setup in advance the current user, and then reference the thing in the singular, e.g.

# in Container model
has_one_of_many :things, :by => :user_id
 
# in application controller
Container.current_thing_user_id = current_user.id 

and then anywhere, you can pull the current user's thing from the container:

record = @container.thing 

Well, that's cool, but in the URLs and routes, we're still required to give a specific thing ID for our RESTful actions, such as GET /things/123 to show, or /things/123/edit to edit. 

What I really want is to keep it generic, so my url's can refer to the current_user's stuff without having to look up its ID when I generate the link.

The simple solution is to support a magic ID the string "my". Thus, we can have

GET /things/my
GET /things/my/edit
PUT /things/my (for update)
etc 

To generate the URL's, you can still use your named resource routes, for example, instead of

thing_path( @thing )
edit_thing_path( @thing ) 

say

thing_path( 'my' )
edit_thing_path( 'my' ) 

and it will generate the expected paths.

Then your controller handles the 'my' param, e.g.

if params[:id]=='my' 
  thing = Thing.find_by_user_id( current_user.id )
else 
  thing = Thing.find( params[:id] )
end

I've taken this a step further. I no longer need to make a distinction between #new and #edit when working on 'my' record. If we go to edit but the record doesn't exist, we just create one then.

def edit
  if params[:id]=='my' 
    thing = Thing.find_or_create_by_user_id( current_user.id )
  else 
    thing = Thing.find( params[:id] )
  end
  ...
end 

 

Note, as written, this assumes each user has just one thing in the container. But you could adjust as needed (e.g. using find_all_by_user_id etc)

 

There are no comments attached to this item.

Post a new comment

How many days in a week?

Name :