Rails:登录或注册后设计重定向到存储位置?

Posted

技术标签:

【中文标题】Rails:登录或注册后设计重定向到存储位置?【英文标题】:Rails: Devise redirect to a stored location after sign in or sign up? 【发布时间】:2011-07-12 10:25:51 【问题描述】:

我正在编写的 Rails 应用程序中使用 Devise,我想让用户在登录或注册后回到他们所在的位置。

例如,如果我有一个受以下保护的“cmets”控制器:

before_filter :authenticate_user!

然后我希望用户点击“立即评论!”按钮(并因此重定向到 CommentsController 中的新操作)登录,然后让 Devise 将它们重定向到 CommentsController 中的新操作(或它们所在的任何位置),而不是应用程序的通用根目录或通用 after_sign_in_path。

查看 Devise 的 RDOC,我发现 this method 看起来好像 Devise 至少有 capability 自己做这样的事情,但我不知道一种方式。

【问题讨论】:

【参考方案1】:

我认为默认情况下 Devise 会保存路线,但您可能正在使用

sign_in @user

这应该会重定向你

sign_in_and_redirect(@user) #assuming you are sigining in that resource

【讨论】:

使用before filter :sign_in_and_redirect(@user) 不起作用。给出的错误表明无法传递参数。 (即“意外字符'('”)如何使用此代码获得 before_filter 的等效行为? 我一直在搞乱它,这就是我想出的。首先,设计存储您在redirect_location_for(:user) 中点击的第一个URL,假设“用户”是您的模型。其次,如果您将redirect_to redirect_location_for(:user) 添加到您的签名控制器中,这一切都应该像魔术一样工作【参考方案2】:

好的,所以我做了更多的实验,并使用 Kormie 的信息,我得到了一个可行的解决方案。

据我所知,before_filter authenticate_user! 确实保存返回用户的路线。我所做的是:

首先,我在控制器顶部添加了一个额外的before_filter

before_filter :store_location
before_filter :authenticate_user!

然后,我在控制器底部写了store_location方法

private

  def store_location
    session[:user_return_to] = any_old_route_path
  end

我并不认为这是完美的,但它对我有用。 (对于其他想要使用它的人来说,它的缺点是每个控制器只支持一个返回路径。这就是我自己所需要的,但与我之前使用的每个应用程序一个返回路径相比,它只是略有改进。 ) 我真的很感谢其他人的见解和建议。

【讨论】:

我有一些看起来像这样的代码:session[:login_redirect] = request.path unless current_user 请注意,我没有使用:user_return_to,因为它已经在内部用于设计 facebook 连接回调。所以改为我自己的变量+签入自定义after_sign_in_path_for【参考方案3】:

你试过after_sign_in_path_for吗?如果您在 ApplicationController 中定义该方法,它应该覆盖每个控制器的默认实现。

【讨论】:

【参考方案4】:

Devise 应该自己做这件事。身份验证用户!当通过 PUT 方法设置操作的路由时,过滤器也不想为我工作。当我在 routes.rb 中将此更改为 GET 时,设计开始按预期工作。

【讨论】:

【参考方案5】:

简单的方法:

# Modified from https://github.com/plataformatec/devise/wiki/How-To:-redirect-to-a-specific-page-on-successful-sign-in
class ApplicationController < ActionController::Base
  def after_sign_in_path_for(resource)
    stored_location_for(resource) || your_defaut_path 
  end
end

【讨论】:

【参考方案6】:

改编自 Devise Wiki 如何:

登录、退出、注册、更新后重定向回当前页面

重定向回“当前页面”涉及将当前 url 保存在会话中,然后在用户通过身份验证/退出后从会话中检索 url。这应该只对 GET 请求真正执行,因为其他 http 方法(POST、PUT、PATCH、DELETE)不是幂等的,不应自动重复。

要为整个应用程序存储位置,请使用 before_action 设置回调(在 4.0 之前的 Rails 版本中使用 before_filter)。

此示例假定您已设置设计来验证名为 User 的类。

# app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  before_action :store_user_location!, if: :storable_location?
  # The callback which stores the current location must be added
  # before you authenticate the user as `authenticate_user!` (or
  # whatever your resource is) will halt the filter chain
  # and redirect before the location can be stored.
  before_action :authenticate_user!

  # To redirect to the stored location after the user signs
  # signs in you would override the after_sign_in_path_for method:
  def after_sign_in_path_for(resource_or_scope)
    # *My note, not wiki*: you may need a fall back as
    # stored_location_for can return nil. I've added root_path
    stored_location_for(resource_or_scope) || root_path
  end
    
  private
    # Its important that the location is NOT stored if:
    # - The request method is not GET (non idempotent)
    # - The request is handled by a Devise controller
    #   such as Devise::SessionsController as that could
    #   cause an infinite redirect loop.
    # - The request is an Ajax request as this can lead
    #   to very unexpected behaviour.
    def storable_location?
      request.get? && is_navigational_format? &&
      !devise_controller? && !request.xhr? 
    end
    
    def store_user_location!
      # :user is the scope we are authenticating
      store_location_for(:user, request.fullpath)
    end
end

参考

Devise How To: Redirect back to current page after sign in, sign out, sign up, update

【讨论】:

以上是关于Rails:登录或注册后设计重定向到存储位置?的主要内容,如果未能解决你的问题,请参考以下文章

登录后设计不会重定向到根目录

用户登录后为什么gem设计重定向注册路径?

注册设计后如何将用户重定向到登录表单?

rails:3 设计注册过滤器链停止为 :require_no_authentication 呈现或重定向

成功登录后重定向或在下一个身份验证中注册凭据类型

Ruby on rails omniauth-twitter 和设计