Edited at

Railsで既存のデータをもとに新しいデータを作成する

More than 3 years have passed since last update.


背景

新しいデータを追加したい。このとき、全部の値を一から記述するのではなく、保存済みのデータをもとに作成したい。

例えば、


方法

dupを使う。例えば、下記のような書籍のデータがあるとき、これを元に続刊のデータを追加したいとする。

[2] pry(main)> Book.first

Book Load (0.2ms) SELECT "books".* FROM "books" ORDER BY "books"."id" ASC LIMIT 1
=> #<Book:0x007fe80c35d9e0
id: 1,
title: "book_1",
description: "desc",
price: 1000,
created_at: Fri, 01 Apr 2016 05:32:20 UTC +00:00,
updated_at: Fri, 01 Apr 2016 05:32:20 UTC +00:00>

dupを使うと以下の様なデータが出来上がる。id,created_at,updated_atnilになっている点に注目。

[3] pry(main)> Book.first.dup

Book Load (0.2ms) SELECT "books".* FROM "books" ORDER BY "books"."id" ASC LIMIT 1
=> #<Book:0x007fe80c26e700
id: nil,
title: "book_1",
description: "desc",
price: 1000,
created_at: nil,
updated_at: nil>

後は複製されたデータを変更し、saveすれば追加できる。

[5] pry(main)> book.title = 'book_2'

=> "book_2"
[6] pry(main)> book.save
(0.1ms) begin transaction
SQL (0.3ms) INSERT INTO "books" ("title", "description", "price", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?) [["title", "book_2"], ["description", "desc"], ["price", 1000], ["created_at", "2016-04-01 05:33:52.992514"], ["updated_at", "2016-04-01 05:33:52.992514"]]
(2.1ms) commit transaction
=> true

保存された内容を見ると、新しく作成されていることがわかる。

[13] pry(main)> Book.all

Book Load (0.1ms) SELECT "books".* FROM "books"
=> [#<Book:0x007fe80c7a9cd8
id: 1,
title: "book_1",
description: "desc",
price: 1000,
created_at: Fri, 01 Apr 2016 05:32:20 UTC +00:00,
updated_at: Fri, 01 Apr 2016 05:32:20 UTC +00:00>,
#<Book:0x007fe80c7a98f0
id: 2,
title: "book_2",
description: "desc",
price: 1000,
created_at: Fri, 01 Apr 2016 05:33:52 UTC +00:00,
updated_at: Fri, 01 Apr 2016 05:33:52 UTC +00:00>]


注意:clonedupは挙動が異なる

"複製"をキーワードにメソッドを探そうとするとcloneが見つかるが、これはdupと挙動が異なるので注意。

[10] pry(main)> book = Book.first

[11] pry(main)> book == book.dup
=> false
[12] pry(main)> book == book.clone
=> true