在编辑时添加,2013-02-11:
我应该更清楚地知道我遇到的问题并不是我无法获得我编写的ERB代码来生成正确的HTML代码。相反,我的Rails安装有时会正确解释HTML代码,因此单击链接会产生正确的效果,有时也会错误地产生“无路由”错误。我在下面的回答中提供了更多细节。
原始问题,2013-02-08:
我正在使用Rails 3.2.11创建一个简单的登录表单。我已经尝试了几种编码表单的“提交”按钮的方法,但由于缺少路由错误,每种方法都失败了。我有一种方法可以工作,并检查了我的代码。但是,现在完全相同的代码失败了。
这是app/views/session/new.html.erb
的代码(我正在使用simple_form
,但不是它的按钮包装器):
<h2>Log in</h2>
<%= simple_form_for :session do |f| %>
<%= f.input :username %>
<%= f.input :password %>
<%= button_to "Submit", session_index_path %>
<% end %>
HTML代码的相关部分是:
<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>
这是我的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
这是命令rake routes
输出的内容:
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
button_to
的目标路径为session_index_path
,这会导致调用create
SessionController
方法 - 并且有一段时间,它确实会被调用。现在,在我重新启动Rails之后,按下按钮会生成一个错误页面,文本为
No route matches [POST] "/session/new"
出于某种原因,Rails开始认为button_to
的目标是session#new
而不是session#create
。就好像它认为它应该调用的HTTP方法是GET而不是POST - 但是,HTML代码显示该方法是post。
顺便说一句,我之前尝试的另一件事是给button_to
操作和方法参数,如文档here所示:
<%= button_to "Submit", options: {action: 'create', method: :post} %>
然后这是生成的:
<form action="/session/new?options%5Baction%5D=create&options%5Bmethod%5D=post" class="button_to" method="post">
也不像我想要的那样。 button_to
的默认HTTP方法是POST,它出现在结果中,但:options
哈希只是添加到URL的末尾,而create
这个词出现在其他地方。< / p>
this question的第一个答案说,与文档说的不同,不应该将button_to
的参数放在哈希中,而是直接给它们。所以,我试过这个:
<%= button_to "Submit", action: 'create' %>
但是,动作create
仍未显示在生成的HTML中:
<form action="/session" class="button_to" method="post">
所以,这些是我在尝试使用命名路径方法之前尝试过的东西,它已经工作了一分钟,但出于某种神秘的原因,它已经不存在了。
任何想法我做错了什么? (这可能是我忽略的一些明显的东西。)
答案 0 :(得分:1)
button_to
文档在几个地方实际上是错误的(请注意我的答案:Why is this button_to rendering incorrectly in Rails 3.2.11?)。要修复“提交”按钮,请使用以下命令:
<%= button_to "Submit", { action: 'create' }, method: :post %>
options
和html_options
哈希需要使用{}
括号定义显式分色,具体取决于您要完成的操作。
create
操作不会显示在网址中,因为POST
到/session
的HTTP方法会路由到create
操作。
答案 1 :(得分:1)
到目前为止,Cyle在上述评论中提出的方法似乎效果最好,即在url: session_index_path
声明中添加simple_form_for
:
<h2>Log in</h2>
<%= simple_form_for :session, url: session_index_path do |f| %>
<%= f.input :username %>
<%= f.input :password %>
<%= button_to "Submit" %>
<% end %>
单击此代码生成的“提交”按钮时,我还没有遇到路由错误。
但是,我不接受这个答案,因为我还没有解决的基本问题是Rails的浮躁;也就是说,以前工作过的代码突然停止工作。例如,今天我首先尝试了这段代码:<%= simple_form_for :session do |f| %>
<%= f.input :username %>
<%= f.input :password %>
<%= button_to "Submit1" %>
<%= button_to "Submit2", session_index_path %>
<% end %>
按“Submit2”按钮有效。但是,当我删除包含按钮“Submit1”的行时,停止并重新启动Rails服务器(正如我在每次尝试之间所做的那样),并重新加载页面,按Submit2按钮产生“无路由”错误,甚至虽然按钮的HTML代码保持不变:
<form action="/session" class="button_to" method="post">
<div>
<input type="submit" value="Submit2" />
<input name="authenticity_token" type="hidden" value="...this value was the same also..." />
</div>
</form>
非常令人费解。可能与我的设置细节有关,虽然它不是那种异国情调。
在编辑时添加:
当我查看由Cyle方法生成的HTML的相关部分时,我注意到它与几乎所有其他情况一样:
<form accept-charset="UTF-8" action="/session" class="simple_form session" method="post" novalidate="novalidate">
<div style="margin:0;padding:0;display:inline">
<input name="utf8" type="hidden" value="✓" />
<input name="authenticity_token" ... />
</div>
...the username and password input fields...
<form action="/session" class="button_to" method="post">
<div>
<input type="submit" value="Submit" />
<input name="authenticity_token" type="hidden" value="voOGIAbJfwvjxVRbk02V5l6zn6iwvOiMvaeauPBIrqU=" />
</div>
</form>
到目前为止,这对我来说可能只是运气。
答案 2 :(得分:1)
问题很可能是在我创建应用程序之后,我决定更改几个类和相关文件的名称。这导致类和文件名在某些上下文中不遵循关于复数名词的Rails约定。例如,我有一个文件session_controller.rb
,其中包含一个名为SessionController
的类;正确的名称为sessions_controller.rb
和SessionsController
。
我创建了一个虚拟Rails应用程序,然后命令rails generate scaffold AtUser
和rails generate scaffold Session
,然后使用生成的文件名和标识符作为纠正实际应用程序的指南。现在,我再也没有得到那些“无路由”的错误。命令rake routes
输出:
at_users GET /at_users(.:format) at_users#index
POST /at_users(.:format) at_users#create
new_at_user GET /at_users/new(.:format) at_users#new
edit_at_user GET /at_users/:id/edit(.:format) at_users#edit
at_user GET /at_users/:id(.:format) at_users#show
PUT /at_users/:id(.:format) at_users#update
DELETE /at_users/:id(.:format) at_users#destroy
sessions POST /sessions(.:format) sessions#create
new_session GET /sessions/new(.:format) sessions#new
session DELETE /sessions/:id(.:format) sessions#destroy
login /login(.:format) sessions#new
logout /logout(.:format) sessions#destroy
root / main#index
在此之前,当我将文件包含在另一个文件中而没有require
d前者位于后者的顶部时,我也看到了“无路由”错误。执行重命名修复后,我尝试重现此错误,并且它确实再次发生:当实际问题是缺少require
语句时,Rails错误地报告了丢失的路由。这表明Rails的错误报告机制存在问题。
感谢用户牛蛙指出我正确的方向。