Почему рельсы default_scope часто рекомендуют?

Везде в Интернете что использование рельсов default_scope - плохая идея, а верхние образы для default_scope в stackoverflow - это о том, как их переписать. Это чувствует себя испорченным и заслуживает явного вопроса (я думаю).

Итак: зачем использовать рельсы default_scope такую ​​плохую идею?

Ответ 1

Проблема 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"

= > Unyscoped удаляет ВСЕ области, которые могут нормально применяться к вашему выбору, включая (но не ограничиваясь ими) ассоциации.

Существует несколько способов перезаписать различные эффекты default_scope. Правильное получение сложных очень быстро, и я бы сказал, что не использовать default_scope, в первую очередь, было бы более безопасным выбором.

Ответ 2

default_scope часто рекомендуется, потому что это иногда неправильно используется для ограничения набора результатов. Хорошим использованием default_scope является упорядочение набора результатов.

Я бы держался подальше от использования where в default_scope и скорее создал область для этого.