Added on edit, 2013-02-11:
I should make it clearer that the problem I'm having is not that I can't get the ERB code I write to produce correct HTML code. Rather, it is that my Rails installation sometimes interprets the HTML code correctly, so that clicking the link has the right effect, and sometimes incorrectly, producing a "No route" error. More details in my answer below.
Original question, 2013-02-08:
I'm making a simple login form using Rails 3.2.11. I've tried several ways of coding the Submit button of the form, but each has failed due to a missing route error. I got one method to work, and checked in my code. However, now the very same code fails.
This is the code of app/views/session/new.html.erb
(I'm using simple_form
, but not its button wrapper):
<h2>Log in</h2>
<%= simple_form_for :session do |f| %>
<%= f.input :username %>
<%= f.input :password %>
<%= button_to "Submit", session_index_path %>
<% end %>
The relevant part of the HTML code that this produces is:
<h2>Log in</h2>
<form accept-charset="UTF-8" action="/session/new" class="simple_form session" method="post" novalidate="novalidate">
<div style="margin:0;padding:0;display:inline">...</div>
...the input fields...
<form action="/session" class="button_to" method="post">
<div>
<input type="submit" value="Submit" />
<input name="authenticity_token" type="hidden" value="...token value here..." />
</div>
</form>
</form>
This is my config/routes.rb
:
MyApp::Application.routes.draw do
resources :at_user
resources :session, :only => [:new, :create, :destroy]
match 'login' => 'session#new', as: :login
match 'logout' => 'session#destroy', as: :logout
root to: 'main#index'
end
This is what the command rake routes
outputs:
at_user_index GET /at_user(.:format) at_user#index
POST /at_user(.:format) at_user#create
new_at_user GET /at_user/new(.:format) at_user#new
edit_at_user GET /at_user/:id/edit(.:format) at_user#edit
at_user GET /at_user/:id(.:format) at_user#show
PUT /at_user/:id(.:format) at_user#update
DELETE /at_user/:id(.:format) at_user#destroy
session_index POST /session(.:format) session#create
new_session GET /session/new(.:format) session#new
session DELETE /session/:id(.:format) session#destroy
login /login(.:format) session#new
logout /logout(.:format) session#destroy
root / main#index
The target path of button_to
is session_index_path
, which should cause the create
method of SessionController
to be called -- and for a while, it did. Now, after I've restarted Rails, pressing the button instead produces an error page, with the text
No route matches [POST] "/session/new"
For some reason, Rails has started to think that the target of button_to
is session#new
instead of session#create
. It's as if it thinks that the HTTP method it's supposed to call is GET instead of POST -- however, the HTML code shows that the method is post.
By the way, another thing I earlier tried was to give button_to
the action and method parameters, as documented here:
<%= button_to "Submit", options: {action: 'create', method: :post} %>
then this is what's generated:
<form action="/session/new?options%5Baction%5D=create&options%5Bmethod%5D=post" class="button_to" method="post">
which doesn't look like what I want, either. button_to
's default HTTP method is POST, which appears in the result, but the :options
hash is just tacked onto the end of the URL, and the word create
appears nowhere else.
The first answer to this question says that, unlike what the documentation says, one should not put the parameters of button_to
in a hash, but give them directly. So, I tried this:
<%= button_to "Submit", action: 'create' %>
However, the action create
still does not show up in the generated HTML:
<form action="/session" class="button_to" method="post">
So, those were things I tried before attempting to using the named path method, which worked for a minute, but for some mysterious reason, doesn't anymore.
Any ideas what I'm doing wrong? (It's probably something obvious I've overlooked.)