button_to只是间歇性地工作,并且经常导致“无路由”错误

时间:2013-02-08 15:38:38

标签: ruby-on-rails button-to

在编辑时添加,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&amp;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">

所以,这些是我在尝试使用命名路径方法之前尝试过的东西,它已经工作了一分钟,但出于某种神秘的原因,它已经不存在了。

任何想法我做错了什么? (这可能是我忽略的一些明显的东西。)

3 个答案:

答案 0 :(得分:1)

button_to文档在几个地方实际上是错误的(请注意我的答案:Why is this button_to rendering incorrectly in Rails 3.2.11?)。要修复“提交”按钮,请使用以下命令:

<%= button_to "Submit", { action: 'create' }, method: :post %>

optionshtml_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="&#x2713;" />
    <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.rbSessionsController

我创建了一个虚拟Rails应用程序,然后命令rails generate scaffold AtUserrails 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的错误报告机制存在问题。

感谢用户牛蛙指出我正确的方向。