发布失败时,防止rails更改url的控制器部分

时间:2012-08-14 19:17:28

标签: ruby-on-rails

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

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

通常情况下,此方法运行正常,但如果用户访问/login并使用不正确的登录详细信息登录,则rails会将网址更改为/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将网址保持为/login,而不是将其更改为/sessions

1 个答案:

答案 0 :(得分:2)

问题是你正在使用宁静的路线。当您发布登录表单时,您正在“创建”会话,这是通过POST到/ sessions来实现的。这是针对SessionsController#create的。 / login是一个单独的,自定义的,非restful路径,它被发送到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,并且识别器应该正确解释路径。