我有一个会话控制器,具有: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
?
答案 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,并且识别器应该正确解释路径。