Проблема 1
Давайте рассмотрим основной пример:
class Post < ActiveRecord::Base
default_scope { where(published: true) }
end
Мотивация использовать значение по умолчанию published: true
может заключаться в том, чтобы убедиться, что вы должны быть явным, когда хотите показывать неопубликованные (частные) сообщения. Все идет нормально.
2.1.1 :001 > Post.all
Post Load (0.2ms) SELECT "posts".* FROM "posts" WHERE "posts"."published" = 't'
Что ж, это в значительной степени то, что мы ожидаем. Теперь попробуем:
2.1.1 :004 > Post.new
=> #<Post id: nil, title: nil, published: true, created_at: nil, updated_at: nil>
И вот у нас есть первая большая проблема с областью действия по умолчанию:
=> default_scope повлияет на инициализацию вашей модели
Во вновь созданном экземпляре такой модели default_scope
будет отражен. Поэтому, хотя вы, возможно, хотели быть уверены, что случайно не перечислили неопубликованные сообщения, теперь вы создаете опубликованные по умолчанию.
Проблема 2
Рассмотрим более сложный пример:
class Post < ActiveRecord::Base
default_scope { where(published: true) }
belongs_to :user
end
class User < ActiveRecord::Base
has_many :posts
end
Получим первые сообщения пользователей:
2.1.1 :001 > User.first.posts
Post Load (0.3ms) SELECT "posts".* FROM "posts" WHERE "posts"."published" = 't' AND "posts"."user_id" = ? [["user_id", 1]]
Это похоже на ожидаемое (обязательно прокрутите страницу до конца вправо, чтобы увидеть часть о user_id).
Теперь мы хотим получить список всех сообщений - включая неопубликованные - скажем, для просмотра вошедшего в систему пользователя. Вы поймете, что вам нужно «перезаписать» или «отменить» эффект default_scope
. После быстрого поиска в Google вы, вероятно, узнаете о unscoped
. Посмотрим, что будет дальше:
2.1.1 :002 > User.first.posts.unscoped
Post Load (0.2ms) SELECT "posts".* FROM "posts"
=> Без области действия удаляет ВСЕ области, которые обычно могут применяться к вашему выбору, включая (но не ограничиваясь) ассоциации.
Есть несколько способов перезаписать различные эффекты default_scope
. Получение этого права очень быстро усложняется, и я бы сказал, что не использовать default_scope
вообще, было бы более безопасным выбором.