Rails 4 - 设计,访客用户导致过滤器链停止

And*_*ers 7 ruby authentication ruby-on-rails devise ruby-on-rails-4

我刚刚开始研究Devise用于用户身份验证的Rails 4(4.2.3)应用程序.我希望用户能够在签署upp之前通过创建测试项目并以guest用户身份登录来使用该应用程序.当用户注册(或在)时,我想将测试项目分配给新的当前用户.

我一直在关注Platformatec的这个指南:https://github.com/plataformatec/devise/wiki/How-To : -Create-a-guest-user

创建guest用户工作,但在注册或使用活动guest虚拟机用户会话时,我收到以下错误:

Filter chain halted as :require_no_authentication rendered or redirected
Run Code Online (Sandbox Code Playgroud)

如果我清除我的会话它是有效的.管理我的访客用户的方法如下所示:

def current_or_guest_user
  if current_user
    if session[:guest_user_id] && session[:guest_user_id] != current_user.id
      logging_in
      guest_user(with_retry = false).try(:destroy)
      session[:guest_user_id] = nil
    end
    current_user
  else
    guest_user
  end
end
Run Code Online (Sandbox Code Playgroud)

如前所述,创建访客用户似乎工作得很好.但这种逻辑永远不会发生:

# should delete the guest user and clear the session. 
if current_user
  if session[:guest_user_id] && session[:guest_user_id] != current_user.id
    logging_in
    guest_user(with_retry = false).try(:destroy)
    session[:guest_user_id] = nil
  end
  current_user
Run Code Online (Sandbox Code Playgroud)

我很确定我的访客用户会话与我的新用户冲突并导致此Devise错误(因为访客用户在注册时永远不会被删除):

Filter chain halted as :require_no_authentication rendered or redirected
Run Code Online (Sandbox Code Playgroud)

我的其他访客用户逻辑看起来或多或少与此链接指南完全相同:https://github.com/plataformatec/devise/wiki/How-To : -Create-a- guest-user .我还添加了身份验证段落/示例中的代码:https://github.com/plataformatec/devise/wiki/How-To : -Create-a-guest-user#authentication-this-may-interfere-with- the -current_user-helper.

关于我缺少什么的任何想法,以及如何current_or_guest_user在使用Devise时让我删除注册和签名的访客用户?

更新

这就是我的路线目前的样子:

devise_for :users, controllers: { sessions: "users/sessions", registrations:  "users/registrations" }

root :to => 'public#index'

resources :apps

get 'users/show', to: "users#show"
get 'users', to: "users#index"

post 'guests/receive_guest', to: "guests#receive_guest"
Run Code Online (Sandbox Code Playgroud)

更新2

该指南有以下声明:

当(以及如果)用户注册或登录时,我们删除访客用户并清除会话变量.

它没有解释如何以及在何处进行.我猜我得current_or_guest_user再次打电话到某个地方.但是我不确定从哪里开始我不熟悉Devise.

更新3

为了使它更清楚一点.这是我想要实现的步骤.

  1. 用户创建一个测试项目.
  2. 创建测试项目后,将创建guest用户和会话.一旦会话结束或#3,访客用户应该被删除.
  3. 如果访客用户注册,他/她应该登录并且测试项目应该分配给新的真实用户.
  4. 访客用户应该被删除.

And*_*ers 1

感谢 skahlert 和 SsouLlesS 的回答。跳过典狱长策略确实有帮助,并且定义回调似乎是一种干净的方法。除此之外我还有其他一些问题。

一是我的自定义 Devise 控制器从未被调用。为此创建了另一个问题:Rails 4 - devise_for not using custom controllers。解决方案是我在模态注册表单中使用了错误的网址。我的表格现在看起来像这样:

= form_for(resource, as: resource_name, url: user_registration_path do |f|
Run Code Online (Sandbox Code Playgroud)

然后我按照斯卡勒特的建议做了,并从我的应用程序中删除了典狱长策略

一旦我的自定义设备Users::RegistrationsController < Devise::RegistrationsController控制器被调用,我决定覆盖创建操作。它尚未经过完全测试,但看起来像这样:

# POST /resource
def create
  # Delete guest user and reset session. 
  new_user_from_guest = guest_user
  guest_user(with_retry = false).try(:destroy)
  session[:guest_user_id] = nil

  build_resource(sign_up_params)

  resource.save
  yield resource if block_given?
  if resource.persisted?
    if resource.active_for_authentication?
      set_flash_message :notice, :signed_up if is_flashing_format?
      sign_up(resource_name, resource)

      # Assign the guest users app to the new current user.
      new_user_from_guest.apps.each do |app|
        app.user_id = current_user.id
        app.save!
      end
      respond_with resource, location: after_sign_up_path_for(resource)
    else
      set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_flashing_format?
      expire_data_after_sign_in!
      respond_with resource, location:  after_inactive_sign_up_path_for(resource)
    end
  else
    # Reset test user if signup fails, I have not tested this part yet. 
    guest_user
    guest_user.apps << new_user_from_guest.apps
    guest_user.save!

    clean_up_passwords resource
    set_minimum_password_length
    respond_with resource
  end
end
Run Code Online (Sandbox Code Playgroud)

现在一切似乎都正常了。可以进行一些重构,并可能尝试 SsouLless 在他的回答中建议的回调方法。