Відповіді:
Розглянемо основний приклад:
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
воля відобразиться. Тож, хоча, можливо, ви хочете бути впевненим, що випадково не перераховуйте неопубліковані публікації, тепер ви створюєте опубліковані за замовчуванням.
Розглянемо більш детальний приклад:
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
в першу чергу, було б більш безпечним вибором.
unscoped
замість default_scope
проблеми 2
default_scope
, коли ви хочете що - то для сортування: default_scope { order(:name) }
.
Ще одна причина , щоб не використовувати default_scope
, коли ви видаляєте екземпляр моделі , яка має 1 до багатьох зв'язок з default_scope
моделлю
Розглянемо для прикладу:
class User < ActiveRecord::Base
has_many :posts, dependent: :destroy
end
class Post < ActiveRecord::Base
default_scope { where(published: true) }
belongs_to :user
end
Виклик user.destroy
видалить усі публікації, які є published
, але не видалить публікації, які є unpublished
. Отже, база даних призведе до порушення зовнішнього ключа, оскільки вона містить записи, що посилаються на користувача, якого ви хочете видалити.
default_scope часто рекомендується проти, оскільки іноді неправильно використовується для обмеження набору результатів. Добре використовувати default_scope - замовити набір результатів.
Я б утримався від використання where
в default_scope і скоріше створив би поле для цього.
default_scope
містить order
. Така поведінка Росії unscoped
досить несподівана.
Для мене це НЕ погана ідея , але слід використовувати з обережністю!. Є випадок, коли я завжди хотів приховати певні записи, коли встановлюється поле.
default_scope
повинен відповідати значенням БД по замовчуванням (наприклад: { where(hidden_id: nil) }
)unscoped
метод, який уникне вашихdefault_scope
Так це буде залежати і від реальних потреб.
Я вважаю default_scope
себе корисним лише для того, щоб в будь-якій ситуації входити asc
чи впорядковуватись якісь параметри desc
. Інакше я уникаю цього, як чуми