如何在client_side_validations gem中覆盖default_scope?

时间:2015-02-14 08:05:26

标签: ruby-on-rails validation devise client-side-validation default-scope

我的大多数模型都有default_scope current_user.company范围。我在注册页面上使用了client_side_validations gem,这意味着没有租户设置。

当唯一性验证程序在@user.email上运行时,default_scope会阻止验证正常运行(因为company_id为nil),因此看起来总是看起来是唯一的结果。

我的用户模型:

# user.rb
...
default_scope { where(company_id: Company.current_id) }
...

验证电子邮件时运行此查询:

Started GET "/validators/uniqueness?case_sensitive=true& \
user%5Bemail%5D=me%2B40%40example.com&_=1423897339854" \
for 76.175.168.2 at 2015-02-14 07:02:30 +0000                        
  User Exists (0.4ms)  SELECT 1 AS one FROM "users" WHERE \
  "users"."company_id" IS NULL AND "users"."email" = 'me@example.com' LIMIT 1

当我从用户模型中删除default_scope时,我得到了正确的结果和正确的验证:

Started GET "/validators/uniqueness?case_sensitive=true& \
user%5Bemail%5D=me%2B40%40example.com&_=1423897339854" \
for 76.175.168.2 at 2015-02-14 07:02:30 +0000
  User Exists (0.4ms)  SELECT 1 AS one FROM "users" WHERE \
  "users"."email" = 'me@example.com' LIMIT 1

当这个gem运行电子邮件验证程序时,覆盖default_scope的最实用的方法是什么?

3 个答案:

答案 0 :(得分:1)

通常我会说:不要使用default_scope,因为你会遇到各种各样的问题。在我看来,默认范围可以订购。

但是你可以这样解决它:

class User < ActiveRecord::Base
 def self.default_scope
    #i don't know what company represents here
    where(company_id: Company.current_id) if Company.present?
 end
end

您可以将默认范围定义为类方法,如上所示。

请参阅doc:http://apidock.com/rails/ActiveRecord/Base/default_scope/class

答案 1 :(得分:0)

我认为覆盖default_scope不是一个好主意。

您应该将逻辑移动到控制器。我不知道你是否正在使用专家。它将提供范围功能。

如果没有,请尝试将此范围移至控制器。

def current_users
   @users||= User.where(company_id: Company.current_id)
end

答案 2 :(得分:0)

我最终在我的应用程序中修补了宝石修补我的问题。我还将更改提交给宝石作者,因为我不确定这是一个错误还是他们原来想要的行为。

# lib/client_side_validations/active_record/middleware.rb

def self.is_unique?(klass, attribute, value, params)
  ...
  !klass.where(relation).exists?
end

# patched the above line to: !klass.unscoped.where(relation).exists?