3
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

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

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

概要 要件

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

Bootstrap4、Rails6

完成(目標物)

スクリーンショット 2020-03-21 10.43.48.png

スクリーンショット 2020-03-21 10.44.42.png

1、model

modelにstatusカラムを追加

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で0を指定
null: falseで、指定したカラムに空保存を防ぐ

rails db:migrate

enum定義
下書き:0
公開: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

しかしこのままだと、紐づくモデルまでは効かないので、各コントローラーの見せたくないアクションにも追記

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 %>

スクリーンショット 2020-03-21 10.44.42.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 %>

スクリーンショット 2020-03-21 11.19.58.png

終わりに

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

参考記事

『Rails』enumを使って下書き記事と公開記事を保存できるようにした
link_to でenumのステータスを変更する方法
Rails enumについてまとめておく

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
3
Help us understand the problem. What are the problem?