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]