Rails API 論理削除の実装

# はじめに
業務のタスクの中で論理削除を実装するタスクが有りましたので、備忘録として書き起こすことにしました。至らぬ点はご容赦ください。。。

# そもそも論理削除とは？
https://www.tutitatu.com/%E3%80%8C%E8%AB%96%E7%90%86%E5%89%8A%E9%99%A4%E3%80%8D%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9%E3%82%84%E6%84%8F%E5%91%B3%E3%80%81%E4%BE%8B%E6%96%87%E3%82%84%E9%A1%9E%E7%BE%A9%E8%AA%9E%E3%82%92%E5%BE%B9/#i-2

↑こちらによると
> データベースのレコードを削除する際にフィールド値を変更する事で削除した扱いにする方式で実際のデータは削除しない事。

とあります。PCの「ゴミ箱」機能がこれにあたるとも書かれていました。
論理削除を実装するメリットとしては、「あたかも削除をしたかのように振る舞う」のでいざ復旧しようとなるとすぐにできることがメリットとして挙げられます。

# どのように実装するかイメージしてみる
実際に削除するのではなく、「あたかも削除をしたかのように振る舞う」なので「データが削除されている、されていないを判断する機能を実装する」が言い回しとして適当であると考えました。

この考えから実装方針として論理削除を実装したいテーブルに対して「削除されている、削除されていない」を判断するためのカラムを追加し、そのテーブルを参照するapiを改修することで実装が可能ではと検討をつけました。

# 実装してみる！
## テーブルにカラムの追加
既存のテーブルにカラムを追加するのですが以前カラム追加の記事を書きましたので、こちらを参照ください笑

https://qiita.com/hrk_sgymm23/items/5a270b06d63b53eb8cbb

今回の実装ではPostというテーブルに`deleted_at`というdatetime型のカラムを追加し、値が入っているか入っていないかで判断することとしました。

## コントローラーを編集(updateメソッド)
まずはテーブルのカラムを追加したので実際にそのデータを挿入するメソッド(今回の場合`update`メソッド)を修正します。

(修正前）
```posts_controller.rb
class Api::V1::PostsController < ApplicationController
~省略~
  def update
      @post = Post.find(params[:id])
      @post.update!(
          title: paramas[:title],
          content: paramas[:content]
      )
      render json: { status: 200, posts: @post }
  end    
~省略~
```
(修正後)
```posts_controller.rb
class Api::V1::PostsController < ApplicationController
~省略~
  def update
      @post = Post.find(params[:id])
      @post.update!(
          title: paramas[:title],
          content: paramas[:content],
          # 現在日時をupdate_atに挿入する文を追加
          deleted_at: Time.now
      )
      render json: { status: 200, posts: @post }
  end    
~省略~
```

## コントローラーを編集(indexメソッド)
postを参照する箇所は他にも有りましたが、今回は`index`メソッドのみ紹介します。

(修正前）
```posts_controller.rb
class Api::V1::PostsController < ApplicationController
    def index
        @posts = Posts.all
        render json: { status: 200, posts: @posts }
    end
~省略~
```

(修正後）
```posts_controller.rb
class Api::V1::PostsController < ApplicationController
    def index
        # 検索条件を修正(deleted_atがnilのものを抽出)
        @posts = Posts.where.not(deleted_at: nil)
        render json: { status: 200, posts: @posts }
    end
~省略~
```



一旦、実装ができたので先輩にレビューをお願いしたところ「ActiveRecordのデフォルトスコープ」を利用すると参照するメソッドの改修は、やらなくて済むのではないかとアドバイスを頂き、実装してみることとしました。

以下公式ドキュメント

https://railsguides.jp/active_record_querying.html#%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%97%E3%82%92%E9%81%A9%E7%94%A8%E3%81%99%E3%82%8B

# デフォルトスコープの適用
postモデルを改修します。
```post.rb
class Post < ApplicationRecord
# 追加
default_scope { where.not(deleted_at: nil) }

end
```

コントローラーの改修したpostsを参照するメソッドは改修前の状態に戻しておきます。


# 終わりに
今回はrails apiで論理削除の実装を紹介してみました。
業務に入りたての頃は実装に取り組む上で「とりあえず動くものを。。。！」というマインドで取り組んでいましたが、より良いコードを書くことにはそのマインドではまだまだだということを業務の中で感じるが多かったです。コードの可読性や再利用性などを考慮する必要があると感じました。

一人前のエンジニアになるのはまだまだかも知れませんが、細い一歩一歩を積み重ねていければと思います。
読んでくださった方ありがとうございました！

# 参考

https://qiita.com/Sobue-Yuki/items/cf3e175614a14e06eab2#%E5%89%8A%E9%99%A4%E5%89%8A%E9%99%A4%E6%B8%88%E4%BB%A5%E5%A4%96%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84%E3%82%88%E3%81%86%E3%81%AB%E3%81%99%E3%82%8B

https://qiita.com/kazasiki/items/8b5be52da6162b34b2b7