Rails:ActiveRecord的default_scope和类继承

csc*_*sch 5 inheritance activerecord default-scope ruby-on-rails-3.2

我的应用不仅有用户,还有管理员和超级管理员.由于所有三个共享相同的属性,我只想使用一个具有附加属性"角色"的表,可以是"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
Run Code Online (Sandbox Code Playgroud)

现在我想做一些事情SuperAdmin.all,只得到SuperAdmins.使用default_scope似乎让我在那里:

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

  # ...
end
Run Code Online (Sandbox Code Playgroud)

现在我也将一个default_scope添加到Admin:

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

  # ...
end
Run Code Online (Sandbox Code Playgroud)

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

csc*_*sch 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
Run Code Online (Sandbox Code Playgroud)

SuperAdmin.all应该按预期工作.


Edm*_*Lee 8

任何像我一样绊倒这个的人,还有另一种选择(更好的 imo)。

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

class Admin < User
  # This line will clear all the default_scopes defined in parent classes
  self.default_scopes = []
  default_scope { ... }
end
Run Code Online (Sandbox Code Playgroud)

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

self.default_scopes = default_scopes + [scope]
Run Code Online (Sandbox Code Playgroud)