Rails 4 – 设计,访客用户导致filter链停止

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

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

创建访客用户是有效的,但在注册或使用活动访客用户会话时,我收到以下错误:

 Filter chain halted as :require_no_authentication rendered or redirected 

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

 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 

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

 # 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 

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

 Filter chain halted as :require_no_authentication rendered or redirected 

我的其他访客用户逻辑看起来或多或少与此链接指南完全相同: https : //github.com/plataformatec/devise/wiki/How-To : -Create-a- guest-user。 我还添加了身份validation段落/示例中的代码: 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" 

更新2

该指南有以下声明:

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

它没有解释如何以及在何处进行。 我猜我必须再次在某处调用current_or_guest_user 。 但是我不确定自从我对Devise不熟悉的地方。

更新3

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

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

上面的答案没有解释,因为你还没有定义你的回调,所以没有调用loggin_in方法

在ApplicationController中,您需要定义然后设置回调,如下所示:

 define_callbacks :logging_in_user set_callback :logging_in_user, :before, :transfer_guest_user_actions_to_current_user def transfer_guest_user_actions_to_current_user # todo end 

你有没有尝试使用devise-guests gem? 它实现了开箱即用的function,而不是从头开始……

检查此示例控制器正在实现访客登录。 希望能帮助到你。

我认为问题是由指南中引用的guest_user warden策略引起的。 由于Devise在登录前检查有效的warden会话,因此会出现重定向和flash消息:

 if authenticated && resource = warden.user(resource_name) flash[:alert] = I18n.t("devise.failure.already_authenticated") redirect_to after_sign_in_path_for(resource) end 

所以,如果你不严格需要认证! 在guest用户上工作的方法,你可以简单地停用该策略,它应该工作。

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

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

 = form_for(resource, as: resource_name, url: user_registration_path do |f| 

然后我按照skahlert的建议做了,并从我的应用程序中删除了warden策略 。

一旦我的自定义设计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 

一切似乎现在都有效。 可以做一些重构,并可能尝试SsouLlesS在他的回答中建议的回调方法。