clone と dup の違い
-
clone
- shallow コピー
- id を保持する
- タイムスタンプやロックに関する属性を保持する
-
属性はコピーしない
- つまり、clone したオブジェクトの属性を変更すると、元のオブジェクトの属性も (同じオブジェクトなので) 変更されてしまう
- アソシエーションはコピーしない
-
dup
- shallow コピー
- id は保持しない (新規レコード)
- タイムスタンプやロックに関する属性は保持しない
- 属性をコピーする
- アソシエーションはコピーしない
yoyo = Yoyo.find_by!(name: 'モジョ')
cloned_yoyo, duped_yoyo = yoyo.clone, yoyo.dup
# duped_yoyo は新規レコード扱い。
[yoyo.id, cloned_yoyo.id, duped_yoyo.id]
#=> [1, 1, nil]
[yoyo.new_record?, cloned_yoyo.new_record?, duped_yoyo.new_record?]
#=> [false, false, true]
# duped_yoyo は changes_to_save が発生する。
cloned_yoyo.changes_to_save
#=> {}
duped_yoyo.changes_to_save
#=> {"brand_id"=>[nil, 1], "name"=>[nil, "モジョ"], "diameter"=>[nil, 57.0], "width"=>[nil, 47.33], "weight"=>[nil, 67.8]}
# duped_yoyo はタイムスタンプを引き継がない。
cloned_yoyo.values_at(:created_at, :updated_at)
#=> [Fri, 11 Oct 2024 00:47:11.789479000 UTC +00:00, Fri, 11 Oct 2024 00:47:11.789479000 UTC +00:00]
duped_yoyo.values_at(:created_at, :updated_at)
#=> [nil, nil]
# cloned_yoyo は属性のオブジェクトを引き継ぐ (同じ object_id) 。
# duped_yoyo は属性のオブジェクトは引き継がない。
[yoyo.name.object_id, cloned_yoyo.name.object_id, duped_yoyo.name.object_id]
#=> [567340, 567340, 831580]
# cloned_yoyo も duped_yoyo もアソシエーションを引き継ぐ。
# cloned_yoyo はアソシエーションのオブジェクトを引き継ぐ (同じ object_id) 。
# duped_yoyo はアソシエーションのオブジェクトは引き継がない。
[yoyo.brand.id, cloned_yoyo.brand.id, dup_yoyo.brand.id]
#=> [1, 1, 1]
[yoyo.brand.object_id, cloned_yoyo.brand.object_id, dup_yoyo.brand.object_id]
#=> [87100, 87100, 87120]
バージョン情報
RUBY_VERSION
#=> "3.3.5"
Rails.version
#=> "7.2.1"
参考
- Ruby on Rails API