1. 概要
- ログイン機能/マイページ機能/投稿機能実装を済み
- Postを 公開(published)/ 下書き(draft) で切替
- 公開投稿は誰でも閲覧、下書きは本人だけ閲覧
- マイページに下書きを表示
追加・編集するファイル
追加(新規)
-
db/migrate/*_add_status_to_posts.rb…postsにstatus:intを追加
編集(追記)
-
app/models/post.rb…enum :statusと可視性メソッド -
config/routes.rb…resources :users, only: :show -
app/controllers/posts_controller.rb… index/show/new/create/edit/update -
app/controllers/users_controller.rb… show(自分の下書き取得) -
app/views/posts/_form.html.erb… 公開設定(ラジオ)を追加 -
app/views/posts/show.html.erb… 「公開中 / 下書き」バッジ表示 -
app/views/users/show.html.erb… 「自分の下書き一覧」を表示
2. migration
コマンドプロンプト
rails g migration AddStatusToPosts status:integer
db/migrate/XXXXXX_add_status_to_posts.rb
class AddStatusToPosts < ActiveRecord::Migration[7.0]
def change
# 0=draft, 1=published(既存の投稿は公開扱いにする)
add_column :posts, :status, :integer, null: false, default: 1
add_index :posts, :status
end
end
コマンドプロンプト
rails db:migrate
3. models
app/models/post.rb
class Post < ApplicationRecord
belongs_to :user
# ======== ここから ========
enum status: { draft: 0, published: 1 }
scope :recent, -> { order(created_at: :desc) }
def visible_to?(viewer)
published? || (viewer && viewer.id == user_id)
end
# ======== ここまで ========
end
4. Controllers
PostsController(公開のみ一覧・本人だけ下書き閲覧)
app/controllers/posts_controller.rb
class PostsController < ApplicationController
before_action :authorize_owner!, only: [:edit, :update, :destroy] # 追加
def index
# @posts = Post.all を下の行に変更
@posts = Post.published.recent.includes(:user)
end
def show
@post = Post.find(params[:id])
# ========以下3行を追加 ======
unless @post.visible_to?(current_user)
redirect_to posts_path, alert: "この投稿は非公開です"
end
#======== ここまで ========
end
def new
# 省略
end
def create
@post = current_user.posts.new(post_params)
if @post.save
# redirect_to action: "index" を下の範囲内のコードに変更
if postdraft.published?
redirect_to :action => "index", :id => postdraft.id, notice: "公開しました" # 追加
else
redirect_to :action => "show", :id => postdraft.id, notice: "下書きを保存しました" # 追加
end
# ======== ここまで ========
else
redirect_to action: "new"
end
end
def edit
# 省略
end
def update
post = Post.find(params[:id])
if post.update(post_params)
# redirect_to ~ tweet.id を下の範囲内のコードに変更
if post.published?
redirect_to :action => "show", :id => postdraft.id, notice: "公開しました"
else
redirect_to :action => "show", :id => post.id, notice: "下書きを更新しました"
end
# ======== ここまで ========
else
redirect_to :action => "new"
end
end
def destroy
# 省略
end
private
# ======= 以下3行を追加 ======
def authorize_owner!
redirect_to posts_path, alert: "権限がありません" unless @post.user_id == current_user.id
end
# ======== ここまで ========
# :statusを追加
def post_params
params.require(:post).permit(:title, :body, :status)
end
end
5. Views
投稿/編集ページ
app/views/posts/new.html.erb
<%= form_for @postdraft do |f| %>
# 省略
# ======== ここから ========
<div class="field">
<%= f.label :公開設定 %><br>
<label>
<%= f.radio_button :status, 'draft', checked: @postdraft.draft? %> 下書き
</label>
<label>
<%= f.radio_button :status, 'published', checked: @postdraft.published? %> 公開
</label>
</div>
# ======== ここまで ========
<%= f.submit "投稿する" %>
<% end %>
edit.html.erb も同様
詳細ページ
app/views/posts/show.html.erb
<div class="post">
<% if @post.draft? %>
<p style="color:#b45309; font-weight:bold;">[下書き(非公開)]</p>
<% elsif @post.published? %>
<p style="color:green; font-weight:bold;">[公開中]</p>
<% end %>
# 省略
</div>
マイページ
app/views/users/show.html.erb
<% if @user == current_user %>
<h2>下書き一覧</h2>
<% @user.posts.draft.each do |d| %>
<div>
<strong>[下書き]</strong>
<%= link_to d.title, post_path(d) %> |
<%= link_to "編集", edit_post_path(d) %>
</div>
<% end %>
<% end %>