-
belongs_to
に条件をつけることで、default_scopeをunscopeすることができます - Rails6.0で確認
# 古きよきdeleted_atで論理削除できるとします
class User < ApplicationRecord
default_scope { where(deleted_at: nil) }
has_many :articles
has_many :comments
end
class Article < ApplicationRecord
# Userが論理削除されていても参照できます
belongs_to :user, -> { unscope(where: :deleted_at) }
end
class Comment < ApplicationRecord
belongs_to :user
# このように、default_scopeをunscopeした関連を定義することもできます
belongs_to :user_with_deleted, -> { unscope(where: :deleted_at) }, foreign_key: :user_id, class_name: 'User'
end
test "article" do
user = User.create! nickname: 'nickname'
user.articles.create! title: 'article_title'
user.update! deleted_at: Time.zone.now
article = Article.first
# userを論理削除した後でも取得できます
assert_equal user, article.user
end
test "comment user" do
user = User.create! nickname: 'nickname'
user.comments.create! text: 'comment'
comment = Comment.first
assert user, comment.user
user.update! deleted_at: Time.zone.now
comment = Comment.first
# 論理削除後はnilになります
assert_nil comment.user
end
test "comment user_with_deleted" do
user = User.create! nickname: 'nickname'
user.comments.create! text: 'comment'
comment = Comment.first
assert user, comment.user_with_deleted
user.update! deleted_at: Time.zone.now
comment = Comment.first
# user_with_deletedを使えば、論理削除後でも取得できます
assert user, comment.user_with_deleted
end
- has_many等でも同様のことができます
- こちらはactiverecordのテストケースから一部抜粋させてもらいました
class Car < ActiveRecord::Base
has_many :bulbs
has_many :all_bulbs, -> { unscope(where: :name) }, class_name: "Bulb"
end
class Bulb < ActiveRecord::Base
default_scope { where(name: "defaulty") }
belongs_to :car
end
test "test" do
car = Car.create!
bulb1 = Bulb.create! name: "defaulty", car: car
bulb2 = Bulb.create! name: "other", car: car
assert_equal [bulb1], car.bulbs
assert_equal [bulb1, bulb2], car.all_bulbs.sort_by(&:id)
end