http post失败后浏览器URL更改

时间:2017-10-07 08:47:02

标签: ruby-on-rails url

我有一个登录页面,验证可以成功与否。这是页面new.html.erb

<%=form_with scope: :session, url: sessions_path, local: true, html: {class: "login-form"} do |f| %>
  <%= f.label :email, t("session.new.email") %>
  <%= f.email_field :email %>

  <%= f.label :password, t("session.new.password") %>
  <%= f.password_field :password %>

  <%= f.submit t('session.new.login'), class: "submit" %>
<% end %>

它与sessions_controller.rb相关联,如下所示:

class SessionsController < ApplicationController

  def create
    # Find the user with the matching email
    user = User.find_by(email: params[:session][:email].downcase)

    # Check the user exists in DB and that the provided password matches
    if user && user.authenticate(params[:session][:password])
      # Log the user through the session helper
      log_in user
      # Redirect to the hive
      redirect_to ideas_path
    else
      # The authentication failed. Display an error message
      flash.now[:error] = I18n.t('session.new.invalid_credentials')
      # The render is done to reinitiate the page
      render :new
    end
  end
end

在我的routes.rb中,我只是为了这个目的:

resources :sessions

执行rails routes时,我有以下声明的路线:

Routes

现在我的问题是登录失败了。在我的控制器中,在这种情况下,我在Flash消息中添加一条消息,然后重新呈现相同的页面new.html.erb。但是在浏览器中,登录请求POST已在网址/sessions上发送。问题是我浏览器上的当前网址变为/sessions而不是留在/sessions/new。这就好像POST请求在我的浏览器中更改了URL。但实际上这只是一个AJAX请求,不是吗?

我发现这个blog post对这种现象有同样的想法(我不是作者)

我找到了一个解决方法,但我更愿意避免使用它并理解bevahior。如果我用下面的方法替换我的路线,这可行:

get    '/login',   to: 'sessions#new'
post   '/login',   to: 'sessions#create'

我可以理解为什么会这样:get和post url是相同的,所以浏览器不会更改其URL。

你有什么想法吗?

修改

我终于找到了解决方案。我不确定这是“轨道方式”,但这可以按预期工作。我刚刚更改了控制器以重定向到同一页面,并通过flash请求传输登录失败信息:

def create
  # Find the user with the matching email
  user = User.find_by(email: params[:session][:email].downcase)

  # Check the user exists in DB and that the provided password matches
  if user && user.authenticate(params[:session][:password])
    # Log the user through the session helper
    log_in user
    # Redirect to the hive
    redirect_to ideas_path
  else
    # The authentication failed. Display an error message through a flash
    # message after redirect to the same page
    redirect_to new_session_path, alert: I18n.t('session.new.invalid_credentials')
  end
end

1 个答案:

答案 0 :(得分:2)

当表单被提交时,浏览器会对/ sessions端点执行常规HTTP POST请求。那里没有AJAX。

您的路线配置方式此POST请求将由您的会话#create action处理。

注意那里的代码。您将看到快乐路径(成功登录)调用redirect_to。如果登录错误,控制器会调用render

不同之处在于,在第一种情况下,响应是浏览器遵循的302重定向。这就是您在浏览器中看到URL更改的原因。在第二种情况下,响应只有200 OK,浏览器要渲染一堆HTML。该网址不会发生变化,因为浏览器未被指示导航到其他位置。

如果您有兴趣,请点击浏览器中的extensive explanation of how redirects work