我刚开始使用Rails 4(4.2.3)应用程序,我使用Devise
进行用户身份验证。我希望用户能够在签署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。我还添加了Authentication段落/示例中的代码:https://github.com/plataformatec/devise/wiki/How-To:-Create-a-guest-user#authentication-this-may-interfere-with-the-current_user-helper。
关于我缺少什么的任何想法,以及如何在使用Devise时让current_or_guest_user
删除注册和签名的访客用户?
更新
这是我的路线目前的样子:
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
让它更清晰一些。这是我想要实现的步骤。
答案 0 :(得分:1)
上述答案缺乏解释,因为您尚未定义回调,因此未调用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?它实现了开箱即用的功能,而不是从头开始......
检查正在实施访客登录的example控制器。希望它有所帮助。
答案 1 :(得分:1)
我认为问题是由指南中引用的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用户上工作的方法,你可以简单地停用该策略,它应该可以工作。
答案 2 :(得分:1)
感谢您的回答skahlert和SsouLlesS。跳过监管策略确实有所帮助,定义回调似乎是一种干净的方法。除此之外我还有其他一些问题。
一个是我的自定义Devise控制器从未被调用过。为此创建了另一个问题:Rails 4 - devise_for not using custom controllers。解决方案是我在模态注册表单中使用了错误的URL。我的表单现在看起来像这样:
= form_for(resource, as: resource_name, url: user_registration_path do |f|
然后我按照skahlert的建议做了,并从我的应用中删除了warden strategy。
一旦我的自定义设备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在他的回答中建议的回调方法。