Ruby on rails 当Desive用户';你在我的默认范围之外吗?

Ruby on rails 当Desive用户';你在我的默认范围之外吗?,ruby-on-rails,activerecord,devise,warden,default-scope,Ruby On Rails,Activerecord,Devise,Warden,Default Scope,我有一个Rails 4应用程序,它使用Desive 3.4进行身份验证,我已经定制了该应用程序,可以禁止用户(使用一个简单的布尔列users.banked,默认为false)。User模型还有一个default\u作用域,它只返回非禁止用户 问题是——我仍然希望我的被禁止用户能够登录,即使他们在登录后不能做任何事情。(他们基本上只是看到一个页面,上面写着“你被禁止了”)。但似乎默认范围正在绊倒designe。当您登录或呼叫时,例如,authenticate\u user,designe尝试使用基

我有一个Rails 4应用程序,它使用Desive 3.4进行身份验证,我已经定制了该应用程序,可以禁止用户(使用一个简单的布尔列
users.banked
,默认为false)。
User
模型还有一个
default\u作用域
,它只返回非禁止用户

问题是——我仍然希望我的被禁止用户能够登录,即使他们在登录后不能做任何事情。(他们基本上只是看到一个页面,上面写着“你被禁止了”)。但似乎
默认范围
正在绊倒designe。当您登录或呼叫时,例如,
authenticate\u user
,designe尝试使用基本的ActiveRecord方法之一(如
find
find\u by
)查找当前用户,但无法找到,因为它们位于默认范围之外。因此Desive得出结论,用户不存在,登录失败


如何使Deave忽略默认范围?

在Deave和Warden源代码中花了很长的时间后,我终于找到了一个解决方案

简短答复: 将其添加到
用户
类:

def self.serialize_from_session(key, salt)
  record = to_adapter.klass.unscoped.find(key[0])
  record if record && record.authenticatable_salt == salt
end
(注意,我只对ActiveRecord进行了测试;如果您使用的是不同的ORM适配器,您可能需要更改该方法的第一行……但是我不确定其他ORM适配器是否有“default so”的概念

长答覆:
serialize\u from\u session
是从-混合到用户类中的。老实说,我不确定它实际上应该做什么,但它是一个公共方法,并且在Desive API中有文档记录(非常稀少),所以我认为它不太可能在没有警告的情况下从Desive中删除

以下是Desive 3.4.1的原始源代码:

def serialize_from_session(key, salt)
  record = to_adapter.get(key)
  record if record && record.authenticatable_salt == salt
end
问题在于
to_adapter.get(key)
to_adapter
返回一个
OrmAdapter::ActiveRecord
的实例,该实例围绕
User
类,而
to_adapter.get
与调用
User.find
基本相同。(Deviate使用
orm_适配器
gem使其保持灵活性;无论您使用的是ActiveRecord、Mongoid还是任何其他与OrmaAdapter兼容的orm,上述方法都不会修改。)

但是,当然,
User.find
只在默认范围内搜索,这就是为什么它找不到我被禁止的用户。调用
到适配器.klass
直接返回
User
类,然后我可以调用
unscoped.find
搜索所有被禁止的用户,并使被禁止的用户可见。所以工作路线是:

record = to_adapter.klass.unscoped.find(key[0])
请注意,我传递的是
key[0]
而不是
key
,因为
key
是一个数组(在本例中是一个元素),将数组传递给
find
将返回一个数组,这不是我们想要的

还要注意的是,在真正的Deavise源代码中调用
klass
是个坏主意,因为这意味着你失去了
或Adapter
的优势。但是在你自己的应用程序中,你可以肯定地知道你正在使用哪种ORM(Deavise不知道的东西),具体一点是安全的