【Rails】下書き & 非公開機能
投稿機能に、下書き保存と非公開機能をもたせます。
手順
- statusカラム追加
- postモデルにenum設定
- コントローラ設定
- 投稿view作成
- 公開/下書き/非公開のview管理
投稿や下書き保存、非公開への更新はトグルスイッチで実装。
新規投稿時に、下書きor公開、公開後に、非公開or公開 と表示させる。
下書き保存済みの投稿、非公開の投稿はタブで管理。
以下記事も参考になれば嬉しいです。
実装
1.statusカラム追加
class CreatePosts < ActiveRecord::Migration[6.1]
def change
create_table :posts do |t|
t.references :user, null: false, foreign_key: true
t.string :title, null: false
t.string :link, null: false
t.integer :status, default: 0, null: false
t.timestamps
end
end
end
enum管理なのでinteger
型にします。
Postテーブルは以下のようにしています!
2. postモデルへenum追記
:
enum status: { published: 0, draft: 1, unpublished: 2 }
:
以下の通りです。
0: 公開中
1: 下書き
2: 非公開
非公開はprivateを使おうと思ったのですが、Rubyの予約語なので避けることをおすすめします。
3. コントローラ設定
長いので2つに分けます。
- createセクション
class Public::PostsController < ApplicationController
def new
@post = Post.new
end
def create
@user = current_user
@post = Post.new(post_params)
@post.user_id = @user.id
if params[:draft].present?
@post.status = :draft
else
@post.status = :published
end
if @post.save
if @post.draft?
redirect_to dashboard_posts_path, notice: '下書きが保存されました。'
else
redirect_to post_path(@post), notice: '投稿が公開されました。'
end
else
render :new
end
end
:
:
解説:
- 投稿のステータス設定
if params[:draft].present?
@post.status = :draft
else
@post.status = :published
end
フォームから送信されたdraft
パラメータの有無で、投稿のステータスを「下書き」か「公開」かを設定する。
- updateセクション
def edit
@post = Post.find(params[:id])
@user = current_user
end
def update
@user = current_user
@post = Post.find(params[:id])
@post.assign_attributes(post_params)
if params[:draft].present?
@post.status = :draft
notice_message = "下書きを保存しました。"
redirect_path = dashboard_posts_path
elsif params[:unpublished].present?
@post.status = :unpublished
notice_message = "非公開にしました。"
redirect_path = dashboard_posts_path
else
@post.status = :published
notice_message = "投稿を更新しました。"
redirect_path = post_path(@post)
end
if @post.save
redirect_to redirect_path, notice: notice_message
else
render :edit
end
end
:
private
def post_params
params.require(:post).permit(:title, :content, :status)
end
end
解説:
- 投稿のステータス設定
if params[:draft].present?
@post.status = :draft
notice_message = "下書きを保存しました。"
redirect_path = dashboard_posts_path
elsif params[:unpublished].present?
@post.status = :unpublished
notice_message = "非公開にしました。"
redirect_path = dashboard_posts_path
else
@post.status = :published
notice_message = "投稿を更新しました。"
redirect_path = post_path(@post)
end
このコードは、投稿を更新する際に、フォームに含まれる特定のパラメータをチェックして投稿のステータスを設定している。このパラメータは、ユーザーがクリックしたボタンに合わせて設定される。
-
params[:draft].present?
は、送信されたパラメータの中にdraft
というキーが存在するかをチェック。ユーザーが「下書き保存」ボタンをクリックした場合にtrueになる。 -
params[:unpublished].present?
は、送信されたパラメータの中にunpublished
というキーが存在するかをチェック。「非公開にする」ボタンをクリックした場合にtrueになる。 - 上記のどちらの条件も満たさない場合は、投稿は公開になる。
4. 投稿View作成
ボタンにname
属性を入れることで、公開/下書き/非公開の設定をしてあげます!
トグルスイッチの実装は以下で解説しています。
<div class="btn-group" role="group" id="buttonGroup">
<% if @post.persisted? %>
<% if @post.draft? %>
<%= f.submit '下書き保存', id: 'draftButton', name: 'draft', class: "draft-btn" %>
<%= f.submit '公開する', id: 'publishButton', name: 'published', class: "submit-btn" %>
<% elsif @post.unpublished? %>
<%= f.submit '非公開にする', id: 'unpublishButton', name: 'unpublished', class: "unpublish-btn" %>
<%= f.submit '公開する', id: 'publishButton', name: 'published', class: "submit-btn" %>
<% else %>
<%= f.submit '非公開にする', id: 'unpublishButton', name: 'unpublished', class: "unpublish-btn" %>
<%= f.submit '公開する', id: 'publishButton', name: 'published', class: "submit-btn" %>
<% end %>
<% else %>
<%= f.submit '下書き保存', id: 'draftButton', name: 'draft', class: "draft-btn" %>
<%= f.submit '公開する', id: 'postButton', name: 'post', class: "submit-btn" %>
<% end %>
</div>
解説:
-
<% if @post.persisted? %>
: 投稿がすでにデータベースに存在する(既存の投稿を編集している)場合を条件とする。もし新規投稿でない場合、この条件内のコードが実行。 -
<% if @post.draft? %>
: 投稿が下書き状態であるかどうかを判定。もし下書きの場合、下書き保存と公開するボタンが表示される。 -
<% elsif @post.unpublished? %>
: 投稿が非公開状態であるかどうかを判定。もし非公開の場合、非行化にすると公開するボタンが表示される。 -
<% else %>
: 公開中の投稿の場合、非公開にするボタンと公開するボタンが表示される。 -
<% else %>
: 新規投稿の場合、下書き保存と公開するボタンが表示される。
nameオプションとは
name
オプションは、フォーム内のボタンや入力フィールドに名前をつけるためのもの。ユーザーがフォームを送信するとき、どの要素からのデータかをサーバーに伝えることができる。
今回のコードでは、例えば「下書き保存」ボタンの場合は name: 'draft'
と指定している。サーバーはこの名前を見て、ユーザーが下書きボタンを押したことを把握できる。これにより、コントローラの下書き保存が実行される。
5. 公開/下書き/非公開のview管理
こんな感じで管理。
<div class="container">
<div class="row">
<div class="col-md-6 offset-md-3">
<div class="tabs d-flex justify-content-between align-items-center">
<ul class="nav nav-tabs">
<li class="nav-item">
<a class="nav-link active" data-toggle="tab" href="#published">公開中</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#draft">下書き</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#unpublished">非公開</a>
</li>
</ul>
<%= link_to "新規投稿", new_post_path, class: "new-post-btn ml-auto" %>
</div>
<div class="tab-content">
<div id="published" class="tab-pane fade show active">
<% @published_posts.each do |post| %>
<%= render "mypost", post: post %>
<% end %>
</div>
<div id="draft" class="tab-pane fade">
<% @draft_posts.each do |post| %>
<%= render "mypost", post: post %>
<% end %>
</div>
<div id="unpublished" class="tab-pane fade">
<% @unpublished_posts.each do |post| %>
<%= render "mypost", post: post %>
<% end %>
</div>
</div>
</div>
</div>
</div>
公開ステータスの投稿のみを表示
以下のようにモデルやコントローラで公開ステータスのみのpostを表示させるようにします。
@posts = Post.published.order(created_at: :desc).page(params[:page]).per(12)
まとめ
以上、下書きと非公開の実装でした。nameオプションは結構便利!
意外に下書きと非公開どちらも解説している記事は少なかったので、参考になれば嬉しいです。
間違い等あったらコメントください💦
投稿一覧ページ等では、非公開の投稿が表示されないようにする(公開の投稿のみ取り出す)ことも忘れないようにしてくださいね。
最初は下書き機能だけにしていて、is_draftカラムでboolean型で管理していました。
でも非公開機能もやっぱり欲しい!ってなり、statusカラムに変えてenum管理に切り替えました。
まあまあな時間を使ってしまったので機能追加を見越した設計って大事だなという学び。
Discussion
素晴らしいポートフォリオになりそうですね!
私から一点話したいことがあります。
このような記事は説明してる機能のデータベースの関係のダイアグラムとかを一緒に載せたらいいと思います。
見る人は文章だけしっかり理解できないしわからないのでおすすめです!
コメント嬉しいです!ありがとうございます!体調を崩してしまい返信遅くなりすいません💦