🙄
Rails の through で dependent を設定するとどうなる?
想定しているのは以下のような関連付けをしている際に through
を設定しつつ dependent
も設定したらどうなるのか?という検証。
ActiveRecord::Schema.define do
create_table :users, force: true do |t|
end
create_table :user_blogs, force: true do |t|
t.integer :user_id
t.integer :blog_id
end
create_table :blogs, force: true do |t|
end
end
class User < ActiveRecord::Base
has_many :user_blogs
has_many :blogs, through: :user_blogs, dependent: :destroy
end
class UserBlog < ActiveRecord::Base
belongs_to :user
belongs_to :blog
end
class Blog < ActiveRecord::Base
has_many :user_blogs
end
user = User.new
# through 経由で blog の関連先を扱うことができる
user.blogs.build
user.save!
pp user.reload.blogs
# => [#<Blog:0x0000795dc151d360 id: 1>]
関連付けにもいくつか種類があるんですが一旦中間テーブルを経由して参照する場合にどうなるのか試してみました。
dependent: :destroy
を設定するとどうなるのか
has_many :blogs, through: :user_blogs, dependent: :destroy
のように設定するとどうなるのか、を試してみました。
期待する挙動としては blog
や user_blog
まで含めて削除されてほしいんですが…。
class User < ActiveRecord::Base
has_one :user_blog
has_one :blog, through: :user_blog, dependent: :destroy
end
class UserBlog < ActiveRecord::Base
belongs_to :user
belongs_to :blog
end
class Blog < ActiveRecord::Base
has_one :user_blog
end
user = User.new
user.blogs.build
user.save!
# 削除前は各レコードが存在している
pp User.first
# => #<User:0x0000782157d18350 id: 1>
pp UserBlog.first
# => #<UserBlog:0x000078219862f980 id: 1, user_id: 1, blog_id: 1>
pp Blog.first
# => #<Blog:0x000078219862dae0 id: 1>
user.destroy!
# 削除後は user と user_blog のみ削除されている
pp User.first
# => nil
pp UserBlog.first
# => nil
pp Blog.first
# => #<Blog:0x0000782157d17bd0 id: 1>
実際には user
と user_blog
のみ削除されて blog
は削除されてないみたいですねー。
blog
まで含めて削除するようにしたい場合は UserBlog
側で belongs_to :blog, dependent: :destroy
しておけば期待する挙動にはなります。
class User < ActiveRecord::Base
has_many :user_blogs
has_many :blogs, through: :user_blogs, dependent: :destroy
end
class UserBlog < ActiveRecord::Base
belongs_to :user
belongs_to :blog, dependent: :destroy
end
class Blog < ActiveRecord::Base
has_many :user_blogs
end
user = User.new
user.blogs.build
user.save!
# 削除前は各レコードが存在している
pp User.first
# => #<User:0x0000782157d18350 id: 1>
pp UserBlog.first
# => #<UserBlog:0x000078219862f980 id: 1, user_id: 1, blog_id: 1>
pp Blog.first
# => #<Blog:0x000078219862dae0 id: 1>
user.destroy!
# これはすべて削除される
pp User.first
# => nil
pp UserBlog.first
# => nil
pp Blog.first
# => nil
まあこれはそれはそう、って感じなんですかねえ。
他の関連付けの場合にどうなるのかも気になる。
has_many
じゃなくて has_one
だとどうなる?
おまけ: 上記は has_many
で関連付けしてたんですが has_one
の場合にはどうなるのか試してみました。
class User < ActiveRecord::Base
has_one :user_blog
has_one :blog, through: :user_blog, dependent: :destroy
end
class UserBlog < ActiveRecord::Base
belongs_to :user
belongs_to :blog
end
class Blog < ActiveRecord::Base
has_one :user_blog
end
user = User.new
user.build_blog
user.save!
# 削除前は各レコードが存在している
pp User.first
# => #<User:0x0000782157d18350 id: 1>
pp UserBlog.first
# => #<UserBlog:0x000078219862f980 id: 1, user_id: 1, blog_id: 1>
pp Blog.first
# => #<Blog:0x000078219862dae0 id: 1>
user.destroy!
# 削除後は user のみ削除されている
pp User.first
# => nil
pp UserBlog.first
# => #<UserBlog:0x00007056dafd6050 id: 1, user_id: 1, blog_id: 1>
pp Blog.first
# => #<Blog:0x00007056dafd5dd0 id: 1>
has_one
だと user
のみ削除されて user_blog
と blog
は削除されないみたいですね。
has_many
と何が違うんだろうか。
Discussion