Skip to main content

Понимание .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(...)