I have an app with vanity urls and I've been struggling with allowing the user to update attributes. The edit form is loading correctly, but after the form is submitted, instead of running the update method, rails reroutes to root. Not exactly sure why this is happening....
# users_controller
def edit
@user = User.find(params[:id])
end
def to_param # overridden
username.parameterize
end
def update
@user = User.find(params[:id])
if @user.update_attributes(params[:user])
redirect_to user_url(current_user.username), :flash => { :success => "success" }
else
redirect_to user_url(current_user.username), :error => { :error => "shit" }
end
end
routes
resources :users do
resources :friends
end
match '/:username' => 'users#show', :as => "user"
form
<%= form_for @user do |form| %>
<%= render 'shared/error_messages', :object => form.object %>
<div class="form">
<p> <%= form.label :description, "Message to friends" %> <br />
<%= form.text_area :description %> </p>
<%= form.submit %>
</div>
<% end %>
dev log
Started GET "/users/1/edit" for 127.0.0.1 at Wed Jan 05 19:07:28 -0500 2011
Processing by UsersController#edit as HTML
Parameters: {"id"=>"1"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE ("users"."id" = 1) LIMIT 1
Rendered shared/_error_messages.html.erb (0.6ms)
ApplicationController::current_user
ApplicationController::current_user_session
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE ("users"."id" = 1) LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE ("users"."id" = 1) LIMIT 1
ApplicationController::current_user_session
ApplicationController::current_user
ApplicationController::current_user
Rendered users/edit.html.erb within layouts/application (27.6ms)
Completed 200 OK in 53ms (Views: 38.7ms | ActiveRecord: 0.3ms)
Started POST "/1" for 127.0.0.1 at Wed Jan 05 19:08:06 -0500 2011
开发者_开发技巧 Processing by UsersController#show as HTML
Parameters: {"commit"=>"Update User", "authenticity_token"=>"OM1lIzizuFCYlxC3XmtmG/btqAsyjekHtqsiwlUDn3M=", "utf8"=>"✓", "username"=>"1", "user"=>{"description"=>"Hello people! Give me your address. Get a postcard."}}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE ("users"."username" = '1') LIMIT 1
Redirected to http://0.0.0.0:3000/
ApplicationController::current_user
ApplicationController::current_user_session
User Load (0.3ms) SELECT "users".* FROM "users" WHERE ("users"."id" = 1) LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE ("users"."id" = 1) LIMIT 1
ApplicationController::current_user_session
Completed 302 Found in 102ms
relevant rake routes:
users GET /users(.:format) {:controller=>"users", :action=>"index"}
POST /users(.:format) {:controller=>"users", :action=>"create"}
new_user GET /users/new(.:format) {:controller=>"users", :action=>"new"}
edit_user GET /users/:id/edit(.:format) {:controller=>"users", :action=>"edit"}
user GET /users/:id(.:format) {:controller=>"users", :action=>"show"}
PUT /users/:id(.:format) {:controller=>"users", :action=>"update"}
DELETE /users/:id(.:format) {:controller=>"users", :action=>"destroy"}
@Beerlington. Your answer was very close and led me finding a fix. Defining the method didn't do it but what did was defining the action.
<%= form_for @user, :url => { :action => "update" } do |form| %>
That did the trick for some reason... Not sure why the action wasn't defined as update.
Look at the generated HTML for your form. I'm betting the action looks something like
action="/1"
So when the form is submitted, your route file says
match '/:username' => 'users#show', :as => "user"
and that is where you are sent
Started POST "/1" for 127.0.0.1 at Wed Jan 05 19:08:06 -0500 2011
Processing by UsersController#show as HTML
I think form_for relies on to_param to generate the action for the form. Since you over wrote it, you're getting unintended behavior.
Your code looks fine to me, but the log is showing that the form is not rendering the hidden _method
field containing "put". This could be caused by the form_for helper not recognizing @user as an existing record. I have no idea why this might be happening, but a temporary fix would be to add the following to your form_for helper:
:html => { :method => :put}
精彩评论