Rails:ActiveRecord的default_scope和类继承

时间:2012-09-07 13:38:20

标签: inheritance activerecord ruby-on-rails-3.2 default-scope

我的应用不仅包含用户,还包含管理员和超级用户。由于所有三个共享相同的属性,我只想使用一个具有附加属性“角色”的表,该表可以是“user”,“admin”或“super_admin”:

class User < ActiveRecord::Base
 # with nickname and password
end


class Admin < User

  def power
    puts "admin rights"
  end
end


class SuperAdmin < Admin

  def superpower
    puts "I've got the #{power}!"
  end
end

现在我想做SuperAdmin.all这样的事情来获得SuperAdmins。使用default_scope似乎让我在那里:

class SuperAdmin < Admin
  default_scope where(["role = ?", "super_admin"])

  # ...
end

现在我也向管理员添加了default_scope:

class Admin < User
  default_scope where(["role = ?", "admin"])

  # ...
end

Aaaand ... SuperAdmin.all不再返回任何内容。那是为什么?

2 个答案:

答案 0 :(得分:9)

如果有多个default_scope,ActiveRecord会将它们链接起来。因此,SuperAdmin.all会查找具有“Admin”和“SuperAdmin”角色的用户 - 这种情况永远不会发生。

要解决这个问题,你可以覆盖继承模型的default_scope,所以只需自己定义一个self.default_scope:

 class SuperAdmin < Admin
    def self.default_scope
        where(["role = ?", "super_admin"])
    end
    #...
 end

SuperAdmin.all应该按预期工作。

答案 1 :(得分:3)

任何像我一样对此进行挫折的人,还有另一种选择(更好的imo)。

您可以简单地删除所有default_scopes,它被定义为数组。

class Admin < User
  # This line will clear all the default_scopes defined in parent classes
  self.default_scopes = []
  default_scope { ... }
end

请参阅此处的源代码 https://apidock.com/rails/ActiveRecord/Base/default_scope/class。您可以看到它只是将后续默认范围添加到数组中。

self.default_scopes = default_scopes + [scope]