0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Rails】下書き機能を実装する

Posted at

1. 概要

  • ログイン機能/マイページ機能/投稿機能実装を済み
  • Postを 公開(published)/ 下書き(draft) で切替
  • 公開投稿は誰でも閲覧、下書きは本人だけ閲覧
  • マイページに下書きを表示

追加・編集するファイル

追加(新規)

  • db/migrate/*_add_status_to_posts.rbpostsstatus:int を追加

編集(追記)

  • app/models/post.rbenum :status と可視性メソッド
  • config/routes.rbresources :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 %>
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?