1

我有一个会话控制器,具有 :new、:create 和 :delete 操作。我还有一个检查当前页面控制器的方法:

def controller_for(path)
  Rails.application.routes.recognize_path(path)[:controller]
end

通常,此方法可以正常工作,但是如果用户访问/login并使用不正确的登录详细信息登录,则 rails 会将 url 更改为/sessions并呈现:new操作,此时我上面的方法会引发错误

No route matches "/sessions"

似乎recognize_path正在尝试这样做:

>> r = Rails.application.routes
>> r.recognize_path "/sessions"
=> {:controller=>"sessions", :action=>"index"}

由于我没有索引操作,因此会导致错误。我真正想要的是:

>> r.recognize_path "/login"
=> {:controller=>"sessions", :action=>"new"} 

那么如何强制 rails 将 url 保留为/login登录失败时的 URL,而不是将其更改为/sessions

4

1 回答 1

2

问题是您使用的是宁静的路线。当您发布登录表单时,您正在“创建”一个会话,这是通过 POST 到 /sessions 来实现的。这是针对SessionsController#create. /login 是一个单独的、自定义的、非静态路径,它被发送到SessionsController#new,基本上是 /sessions/new 的别名。

recognize_path当环境没有另外说明时,默认将路径解释为 GET 请求。并且 GET 请求假定/sessions意味着索引视图。

# The recognize_path method in the Rails source:
def recognize_path(path, environment = {})
  method = (environment[:method] || "GET").to_s.upcase
  ...
end

解决此问题的一种方法是更改​​路由。例如,您可以将其添加到您的路线中:

match "/process_login" => "sessions#create", :as => 'process_login'

然后更改您的登录表单以匹配:

<% form_tag process_login_path do %>
  [your login form here]
<% end -%>

现在您将表单发布到 /process_login 而不是 /sessions,并且识别器应该正确解释路径。

于 2012-08-14T20:41:12.960 回答