確認環境
$ bundle exec ruby --version
ruby 2.7.5p203 (2021-11-24 revision f69aeb8314) [x86_64-darwin19]
$ bundle exec rails --version
Rails 6.0.4.6
事前準備
モデル作成
$ rails g model SampleUser name:string
$ rails g model SampleUserItem sample_user_id:integer price:integer name:string
migrate
$ rake db:migrate
リレーションを作成
app/models/sample_user.rb
class SampleUser < ApplicationRecord
has_many :sample_user_items
end
データの初期化メソッドを用意
$ rails c
...
def init_data
SampleUser.delete_all
SampleUserItem.delete_all
u1 = SampleUser.new(name: 'user1')
u1.save
item1 = SampleUserItem.new(sample_user_id: u1.id, name: 'item1', price: 100)
item1.save
item2 = SampleUserItem.new(sample_user_id: u1.id, name: 'item2', price: 200)
item2.save
end
# データを初期化する時にこちらを呼び出してください。
init_data
それぞれのオプションを試す前に、init_data を実行して、データを初期化してください。
挙動確認
:destroy
app/models/sample_user.rb
class SampleUser < ApplicationRecord
has_many :sample_user_items, dependent: :destroy
end
$ rails c
Loading development environment (Rails 6.0.4.6)
irb(main):001:0> SampleUser.last.destroy
(1.1ms) SELECT sqlite_version(*)
SampleUser Load (0.1ms) SELECT "sample_users".* FROM "sample_users" ORDER BY "sample_users"."id" DESC LIMIT ? [["LIMIT", 1]]
(0.1ms) begin transaction
SampleUserItem Load (0.1ms) SELECT "sample_user_items".* FROM "sample_user_items" WHERE "sample_user_items"."sample_user_id" = ? [["sample_user_id", 2]]
SampleUserItem Destroy (0.3ms) DELETE FROM "sample_user_items" WHERE "sample_user_items"."id" = ? [["id", 3]]
SampleUserItem Destroy (0.1ms) DELETE FROM "sample_user_items" WHERE "sample_user_items"."id" = ? [["id", 4]]
SampleUser Destroy (0.2ms) DELETE FROM "sample_users" WHERE "sample_users"."id" = ? [["id", 2]]
(0.8ms) commit transaction
=> #<SampleUser id: 2, name: "user1", created_at: "2022-08-21 07:23:23", updated_at: "2022-08-21 07:23:23">
ちなみに SampleUser.last.delete
では、sample_user_items
は削除されません。
:delete_all
belongs_to の場合は :delete
を使用します。
今回は has_many なので、 :delete_all を使用します。
app/models/sample_user.rb
class SampleUser < ApplicationRecord
has_many :sample_user_items, dependent: :delete_all
end
irb(main):017:0> SampleUser.last.destroy
(0.1ms) SELECT sqlite_version(*)
SampleUser Load (0.2ms) SELECT "sample_users".* FROM "sample_users" ORDER BY "sample_users"."id" DESC LIMIT ? [["LIMIT", 1]]
(0.0ms) begin transaction
SampleUserItem Destroy (0.2ms) DELETE FROM "sample_user_items" WHERE "sample_user_items"."sample_user_id" = ? [["sample_user_id", 3]]
SampleUser Destroy (0.1ms) DELETE FROM "sample_users" WHERE "sample_users"."id" = ? [["id", 3]]
(0.8ms) commit transaction
=> #<SampleUser id: 3, name: "user1", created_at: "2022-08-21 07:27:11", updated_at: "2022-08-21 07:27:11">
:restrict_with_exception
app/models/sample_user.rb
class SampleUser < ApplicationRecord
has_many :sample_user_items, dependent: :restrict_with_exception
end
irb(main):020:0> SampleUser.last.destroy
(0.1ms) SELECT sqlite_version(*)
SampleUser Load (0.2ms) SELECT "sample_users".* FROM "sample_users" ORDER BY "sample_users"."id" DESC LIMIT ? [["LIMIT", 1]]
(0.0ms) begin transaction
SampleUserItem Exists? (0.1ms) SELECT 1 AS one FROM "sample_user_items" WHERE "sample_user_items"."sample_user_id" = ? LIMIT ? [["sample_user_id", 4], ["LIMIT", 1]]
(0.0ms) rollback transaction
Traceback (most recent call last):
1: from (irb):20
ActiveRecord::DeleteRestrictionError (Cannot delete record because of dependent sample_user_items
:restrict_with_error
app/models/sample_user.rb
class SampleUser < ApplicationRecord
has_many :sample_user_items, dependent: :restrict_with_error
end
irb(main):034:0> a = SampleUser.last
SampleUser Load (0.1ms) SELECT "sample_users".* FROM "sample_users" ORDER BY "sample_users"."id" DESC LIMIT ? [["LIMIT", 1]]
=> #<SampleUser id: 5, name: "user1", created_at: "2022-08-21 07:33:14", updated_at: "2022-08-21 07:33:14">
irb(main):035:0> a.destroy
(0.1ms) begin transaction
SampleUserItem Exists? (0.2ms) SELECT 1 AS one FROM "sample_user_items" WHERE "sample_user_items"."sample_user_id" = ? LIMIT ? [["sample_user_id", 5], ["LIMIT", 1]]
(0.1ms) rollback transaction
=> false
irb(main):036:0> a.errors
=> #<ActiveModel::Errors:0x00007f927f6f7750 @base=#<SampleUser id: 5, name: "user1", created_at: "2022-08-21 07:33:14", updated_at: "2022-08-21 07:33:14">, @messages={:base=>["Cannot delete record because dependent sample user items exist"]}, @details={:base=>[{:error=>:"restrict_dependent_destroy.has_many", :record=>"sample user items"}]}>
:nullify
app/models/sample_user.rb
class SampleUser < ApplicationRecord
has_many :sample_user_items, dependent: :nullify
end
irb(main):039:0> SampleUser.last.destroy
(0.1ms) SELECT sqlite_version(*)
SampleUser Load (0.1ms) SELECT "sample_users".* FROM "sample_users" ORDER BY "sample_users"."id" DESC LIMIT ? [["LIMIT", 1]]
(0.1ms) begin transaction
SampleUserItem Update All (0.3ms) UPDATE "sample_user_items" SET "sample_user_id" = ? WHERE "sample_user_items"."sample_user_id" = ? [["sample_user_id", nil], ["sample_user_id", 6]]
SampleUser Destroy (0.1ms) DELETE FROM "sample_users" WHERE "sample_users"."id" = ? [["id", 6]]
(0.8ms) commit transaction
=> #<SampleUser id: 6, name: "user1", created_at: "2022-08-21 07:39:50", updated_at: "2022-08-21 07:39:50">