Rails3 singular route to mask :id
In the Rails Guides under 2.5 Singular Resources, it states
开发者_如何学编程Sometimes, you have a resource that clients always look up without referencing an ID. For example, you would like /profile to always show the profile of the currently logged in user. In this case, you can use a singular resource to map /profile (rather than /profile/:id) to the show action.
So I tried the example:
match "profile" => "users#show"
However, when I attempt to go to the profile_path, it attempts to redirect to the following, where id = :id:
/profile.id
This represents two issues:
- I dont want the id to be displayed at all, and thought this was a routing pattern to mask an id
- Using this method causes the following error. It also causes this error when I attempt to request user_path.
Error:
ActiveRecord::RecordNotFound in UsersController#show
Couldn't find User without an ID
I guess this is because the params being passed through look like this:
{"controller"=>"users", "action"=>"show", "format"=>"76"}
Am I using singular resources correctly?
My UsersController:
def show
@user = User.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @user }
end
end
My routes:
resources :users
match "profile" => "users#show"
First of all, if you want to use profile_url
or profile_path
you have to use :as
like this:
match "/profile" => "users#show", :as => :profile
You can find an explanation here.
Secondly, in your controller you rely on params[:id]
to find the user you are looking for. In this scenario there is no params[:id]
, so you have to rewrite your controller code:
def show
if params[:id].nil? && current_user
@user = current_user
else
@user = User.find(params[:id])
end
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @user }
end
end
Or
get "/profile/:id" => "users#show", :as => :profile
# or for current_user
get "/profile" => "users#show", :as => :profile
or
resource :profile, :controller => :users, :only => :show
It looks for an :id because probably you already have a resource profile in your routes file:
resoruce(s): profile
If it so, try to shift that line under your new line match "profile" => "users#show
It should acquire less priority and your new line should be read before the resource: profile is read.
Let me know if it is the problem and if you solve.
i did this in this way:
resources :users
match "/my_profile" => "users#show", :as => :my_profile
and to make it workable i have to edit my controller code too:
def show
current_user = User.where(:id=> "session[:current_user_id]")
if params[:id].nil? && current_user
@user = current_user
else
@user = User.find(params[:id])
end
respond_to do |format|
format.html # show.html.erb`enter code here`
format.xml { render :xml => @user }
end
end
and at the end just give a link to my_profile:
<a href="/my_profile">My Profile</a>
精彩评论