Многоцелевая проверка с использованием rolify
Можно ли сделать многоцелевую проверку - user.has_role?(:admin, :moderator)
... который, надеюсь, делает один запрос к БД против выполнения user.has_role?(:admin) && user.has_role?
(: модератор), который, очевидно, предполагает посещение БД дважды.
2 ответа
Нет, сейчас вы не можете пропустить такие варианты.
user.has_role?(:admin, :moderator)
Если вы хотите уберечь себя от выполнения нескольких запросов, вы можете сделать что-то вроде
(user.roles & [:admin, :moderator]).present?
Rolify имеет has_any_role?
а также has_all_roles?
методы, которые делают это вполне читабельно. has_any_role?
только ударил в БД один раз, но has_all_roles?
похоже, что он перебирает аргументы вызова has_role?
так что это не полностью решит вашу проблему с многократным попаданием в БД (оно останавливается, когда попадает в первый отрицательный результат, что лучше, чем ничего).
Мне кажется, что вы можете проверить, были ли у пользователя обе роли в одном запросе с помощью:
user.roles.where("name IN (?, ?)", "admin", "moderator").size > 1
Это не сработает, если пользователь может иметь одинаковую роль на разных ресурсах, но вы поняли идею. Другая проблема заключается в том, что он жестко определяет количество проверяемых вами ролей. Вы можете обойти это, создав список аргументов и используя send
но это было бы отчасти уродливо. В качестве альтернативы, если вы знали, что значения, которые вы проверяли, были безопасны, вы могли бы поместить их в массив и сделать:
roles_to_check = ["admin", "moderator"]
user.roles.where(name: roles_to_check).size >= roles_to_check.size