【Ruby on Rails】deep_cloneableを使って投稿や記事をコピー(複製)する方法

【Ruby on Rails】deep_cloneableを使って投稿や記事をコピー(複製)する方法

こんにちは、nishi_talk(@nishi_talk)です。
Railsで投稿できる画面を作っていて似た投稿があった場合、コピーできると便利ですよね!
今回はdeep_cloneableを使って投稿や記事をコピー(複製)する方法をご紹介します。




前提条件

  • ruby 2.5.1
  • Rails 5.2.0

データベース構造

(1)User <-> (多)Post(1) 
mysql> show columns from users;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | int(11)      | NO   | PRI | NULL    | auto_increment |
| name       | varchar(255) | NO   |     | NULL    |                |
| created_at | datetime(6)  | NO   |     | NULL    |                |
| updated_at | datetime(6)  | NO   |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+

mysql> show columns from post;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | int(11)      | NO   | PRI | NULL    | auto_increment |
| created_at | datetime(6)  | NO   |     | NULL    |                |
| updated_at | datetime(6)  | NO   |     | NULL    |                |
| user_id    | int(11)      | NO   | MUL | NULL    |                |
+------------+--------------+------+-----+---------+----------------+

deep_cloneableをインストール

Gemfileに以下を追記。

gem 'deep_cloneable'



$ bundle install

routesの設定

routes.rbにコピー用のURLを用意します。

resources :posts do
  get 'copy'
end

追加されたか確認します。

$ rails routes
・
・
・
# ↓追加されるはず
post_copy POST   /posts/:post_id/copy(.:format)   posts#copy
・
・
・

Controllerの設定

対象の投稿IDを取得して、deep_cloneで複製します。
複製した投稿を保存します。

今回は例として、posts_controller.rbに追加します。

def copy
  @old_post = Post.find_by(id: params[:post_id])
  @post = @old_post.deep_clone
  @post.save
  redirect_to posts_path(@post.id), notice: 'コピーしました。'
end

Viewの設定

<%= link_to post_copy_path(@post.id), data: { confirm: 'コピーしますか?' } do %>
コピーする
<% end %>

表示されたコピーボタンを選択すると対象の投稿がコピーできます。