enumで下書き、公開機能を実装

いろいろやったので備忘録

## 概要 要件
- 美容室のページに下書き機能を実装する
- デフォルト下書き、編集→保存、及び、ボタンでステータスを変更できるようにする
- その美容室に紐づくモデル（スタイリスト、スタイル、メニュー）も非公開にする
- ログインしていれば下書き状態のものも見ることができる
- ログインしていても他のユーザーの非公開ページは見れない

Bootstrap4、Rails6

## 完成（目標物）
<img width="769" alt="スクリーンショット 2020-03-21 10.43.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88038/c64fd31d-f771-d467-8b3a-e55434f43484.png">

<img width="343" alt="スクリーンショット 2020-03-21 10.44.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88038/174209e4-6be5-2cc7-3896-d8262976e3d0.png">

## 1、model
modelにstatusカラムを追加

```bash
rails generate migration AddStatusToSalon status:integer
```
追記

```db/migrate/xxxxxxxx_add_status_to_salon.rb
 def change
    add_column :salons, :status, :integer, default: 0, null:false
 end
```
defaultで０を指定
null: falseで、指定したカラムに空保存を防ぐ

``` bash
rails db:migrate
```

enum定義
下書き：０
公開：1

``` salon.rb
  enum status: { draft: 0, published: 1, deleted: 2 }
  validates :status, inclusion: { in: Salon.statuses.keys }
```
## 2、View 

``` salons/edit.html.erb
<div class="form-group">
   <label>ステータス</label><br>
   <%= form.select :status, [["下書き", "draft"],["公開", "published"]], id: "status", class: "form-control" %>
 </div>
```

## 3、controller
元のソース

``` salons_controller.rb
  def show
      @hairstyles = @salon.hairstyles.order(id: "desc")
      @hairstyles = @salon.hairstyles.rank(:row_order)
      render layout: false
  end
```

下書き状態の時でログインしていれば見れる。
公開だったら見れる

``` salons_controller.rb
  def show
    if (@salon.published? || user_signed_in? && @salon.draft?)
      @hairstyles = @salon.hairstyles.order(id: "desc")
      @hairstyles = @salon.hairstyles.rank(:row_order)
      render layout: false
    else
      flash[:alert] = "非公開です ログインしてください"
      redirect_to root_path
    end
  end
```
ログインしていても他のアカウントのページは見れない（自分のページしか見れない）

``` salons_controller.rb
  def show
    if (@salon.draft? && @salon.user.id != current_user.id)
      flash[:alert] = "権限がありません"
      redirect_to root_path
    elsif (@salon.published? || user_signed_in? && @salon.draft?)
      @hairstyles = @salon.hairstyles.order(id: "desc")
      @hairstyles = @salon.hairstyles.rank(:row_order)
      render layout: false
    else
      flash[:alert] = "非公開です ログインしてください"
      redirect_to root_path
    end
  end
```
しかしこのままだと、紐づくモデルまでは効かないので、各コントローラーの見せたくないアクションにも追記

``` ruby
if (@salon.draft? && @salon.user.id != current_user.id)
      flash[:alert] = "権限がありません"
      redirect_to root_path
elsif (@salon.published? || user_signed_in? && @salon.draft?)
   xxxxxxxxx
   xxxxxxxxx
end
```

## 4、ボタンでステータスを変更できるようにする

### modeにメソッドを作成

draftだったらpublishedに変更
publishedだったらdraftに変更

``` salon.rb
def toggle_status!
  draft? ? published! : draft!
end
```
### controller

``` salons_controller.rb
  def toggle_status
    @salon.toggle_status!
    redirect_to dashboard_path, notice: 'ステータスを変更しました'
  end
```

### routes

``` routes.rb

  resources :salons do
    patch :toggle_status
  end

```

### view
店舗一覧ページ

``` dashborad.html.erb
<% if (salon.published?) %>
    <%= link_to "非公開にする", salon_toggle_status_path(salon), method: :patch, class: "btn btn-outline-danger" %>
<% else %>
    <%= link_to "公開する", salon_toggle_status_path(salon), method: :patch, class: "btn btn-outline-danger" %>
<% end %>
```

<img width="343" alt="スクリーンショット 2020-03-21 10.44.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88038/c1abaabb-a6c1-e40b-3023-7fe793b01737.png">

### ステータス表示

```
 <% if (salon.published?) %>
      <div class="btn btn-primary mr-5 float-left">公開中</div>
 <% else %>
      <div class="btn btn-success mr-5 float-left">下書き</div>
 <% end %>
```
<img width="196" alt="スクリーンショット 2020-03-21 11.19.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88038/96e28209-30f6-eb07-7661-c2619ad5de7c.png">


## 終わりに
書き方等、変なところあれば、ご指摘ください。
以下、記事参考にさせていただきました。

## 参考記事
[『Rails』enumを使って下書き記事と公開記事を保存できるようにした](https://pgmg-rails.com/blogs/21)
[link_to でenumのステータスを変更する方法](https://www.akito.io/posts/link-to-enum-change)
[Rails enumについてまとめておく](https://qiita.com/shizuma/items/d133b18f8093df1e9b70)