はじめに
ActiveRecordオブジェクトに対してcloneとdupメソッドを実行した結果をまとめます。
結果
dup | clone | |
---|---|---|
id | nil | コピー元と同じ |
new_record? | true | false |
実行例
dup
- idはnilになる
irb(main):001:0> company = Company.first
Company Load (1.2ms) SELECT `companies`.* FROM `companies` ORDER BY `companies`.`id` ASC LIMIT 1
=> #<Company id: 1, name: "テスト会社">
irb(main):002:0> dup_company = company.dup
=> #<Company id: nil, name: "テスト会社">
- object_idは異なる
irb(main):003:0> company.object_id
=> 29520
irb(main):004:0> dup_company.object_id
=> 29540
-
new_record?
は trueになる- 保存しないと永続化しない
- アソシエーションは外れる
- 保存時は
before_save
、before_create
が呼ばれる
irb(main):005:0> dup_company.new_record?
=> true
irb(main):006:0> dup_company.employees
=> #<ActiveRecord::Associations::CollectionProxy []>
clone
- idはコピー元と同じになる
irb(main):001:0> company = Company.first
Company Load (1.2ms) SELECT `companies`.* FROM `companies` ORDER BY `companies`.`id` ASC LIMIT 1
=> #<Company id: 1, name: "テスト会社">
irb(main):007:0> clone_company = company.clone
=> #<Company id: 1, name: "テスト会社">
- object_idは異なる
irb(main):003:0> company.object_id
=> 29520
irb(main):008:0> clone_company.object_id
=> 29560
-
new_record?
は falseになる- アソシエーションはそのまま維持される
- 保存時は
before_save
、before_update
が呼ばれる
irb(main):013:0> company.employees
=> #<ActiveRecord::Associations::CollectionProxy [#<Employee id: 1, company_id: 1, ....>]>
irb(main):014:0> clone_company.employees
=> #<ActiveRecord::Associations::CollectionProxy [#<Employee id: 1, company_id: 1, ....>]>
- コピー元オブジェクトの値を変更すると、save前でもcloneしたオブジェクトの値も変更される
irb(main):010:0> company.name = "テスト会社2"
=> "テスト会社2"
irb(main):011:0> company
=> #<Company id: 1, name: "テスト会社2">
irb(main):012:0> clone_company
=> #<Company id: 1, name: "テスト会社2">
おわりに
dup
はオブジェクトの内容をコピーした新しいオブジェクトを生成し、 clone
はオブジェクトの内容をコピーし、freeze, 特異メソッドなどの情報も含めた完全な複製を作成します。
`
両方ともオブジェクトの指している先まではコピーしないシャローコピ―であることにも気を付けたいと思います。
参考