Oh my, my, my
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.



