Rails: ActiveRecord default_scope и наследование классов

Мое приложение имеет не только пользователей, но и администраторов и SuperAdmins. Поскольку все три имеют одни и те же атрибуты, я бы хотел использовать только одну таблицу с дополнительным атрибутом "роль", который может быть "пользователь", "администратор" или "супер_админ":

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 для Admin:

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

  # ...
end

Аааа... SuperAdmin.all больше ничего не возвращает. Это почему?

2 ответа

Решение

Если существует несколько областей по умолчанию, ActiveRecord объединяет их в цепочку. Таким образом, SuperAdmin.all ищет пользователей с ролью "Администратор" И "SuperAdmin", чего никогда не произойдет.

Чтобы обойти это, вы можете переопределить default_scope унаследованной Модели, поэтому просто определите self.default_scope самостоятельно:

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

SuperAdmin.all теперь должен работать как положено.

Любой, кто сталкивается с этим, как я, есть другой вариант (лучше 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]
Другие вопросы по тегам