Понимание .unscoped в ActiveRecord
Метод .unscoped в ActiveRecord используется для отмены всех заданных скоупов (по умолчанию или вручную определённых), временно возвращая модель к «чистому» состоянию запроса. Это мощный инструмент, но требует осознанного применения, чтобы не нарушить бизнес-логику или безопасность приложения.
Что делает .unscoped
Представим, у вас есть модель с default_scope:
class Article < ApplicationRecord
default_scope { where(published: true) }
end
Article.all # => вернёт только опубликованные статьи
Теперь вы хотите получить все статьи, включая неопубликованные:
Article.unscoped.all # => вернёт все статьи, игнорируя default_scope
Когда использовать .unscoped
1. Явное нарушение default_scope
Когда нужно получить записи, которые по умолчанию скрыты, например, удалённые или черновики:
User.unscoped.find_by(email: 'deleted@example.com')
Если User использует default_scope { where(deleted_at: nil) }, то unscoped поможет достать удалённого пользователя.
2. Миграции и административные скрипты
Когда вы пишете rake-задачу или сервисный скрипт, и хотите быть уверены, что забираете все записи независимо от фильтров:
Article.unscoped.update_all(published: true)
3. Тонкое объединение с другими условиями
Можно частично снять скоуп только с конкретной модели в объединении:
Comment.joins(:user).merge(User.unscoped.where(banned: true))
Когда не стоит использовать .unscoped
1. В контроллерах и публичных API
Вы можете случайно раскрыть удалённые, скрытые или конфиденциальные записи, нарушив безопасность:
# Плохо
User.unscoped.where(role: 'admin') # вернёт и удалённых пользователей
2. Если есть soft-delete или multitenancy
Модели с acts_as_paranoid, discard, или apartment могут работать некорректно при отключении скоупов:
Tenant.current = my_tenant
User.unscoped.all # пробьёт границы арендатора!
Альтернатива: .unscope(...)
Если нужно снять не все, а только некоторые условия:
Article.where(published: true, category: 'Tech')
.unscope(:where => :published)
Заключение
| Сценарий | Использовать .unscoped? |
|---|---|
| Извлечь soft-deleted записи | ✅ |
| Миграции, rake, сервис-обход | ✅ |
| Публичный API | 🚫 |
| Обход арендаторов (multitenant) | 🚫 |
| Частичное снятие условий | → .unscope(...) |