LoginSignup
25
19

More than 3 years have passed since last update.

【Rails】投稿機能に公開・非公開機能を追加した時の実装手順

Posted at

はじめに

制作しているポートフォリオに記事の公開・非公開機能を追加したので、実装手順を紹介します。
記事を投稿したけど、一旦非公開にしたい時があると思うので、実装してみました。

前提

  • kaminariのgemの機能を使用し、非公開記事一覧取得してます
  • deviseのgemの機能を使用し、他ユーザーを非公開記事からリダイレクトさせてます

バージョン情報

  • Ruby 2.6.3
  • Rails 6.0.2.1

実装した手順

postsテーブルにstatus用のカラムを追加

$ rails g migration Add_status_To_posts status:integur
db/migrate/20201111213454_add_status_to_posts.rb
class AddStatusToPosts < ActiveRecord::Migration[6.0]
  def change
    add_column :posts, :status, :integer, null: false, default: 0
  end
end

モデルを定義

app/models/post.rb
class Post < ApplicationRecord

#・・・省略

  enum status: { public: 0, private: 1 }, _prefix: true

#・・・省略

end

上記のように_prefix: trueを記述してない状態でブラウザを開いたら、下記のエラーが出た。
エラー文を確認すると、publicというメソッドが重複しているとのこと。
重複してエラーが出ていなければ_prefix: trueを記述しなくてもOK。

log/development.log
ArgumentError (You tried to define an enum named "status" on the model "Post", but this will generate a class method "public", which is already defined by Active Record.):

app/models/post.rb:19:in `<class:Post>'
app/models/post.rb:1:in `<main>'
app/controllers/posts_controller.rb:85:in `set_post'
Started GET "/posts/3" for 127.0.0.1 at 2020-11-12 06:52:36 +0900
Cannot render console from 172.22.0.1! Allowed networks: 127.0.0.0/127.255.255.255, ::1
  [1m[35m (1.2ms)[0m  [1m[35mSET NAMES utf8mb4,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483[0m
Processing by PostsController#show as HTML
  Parameters: {"id"=>"3"}
Completed 500 Internal Server Error in 27ms (ActiveRecord: 0.0ms | Allocations: 5566)

投稿編集ページで投稿ステータスを選択できるようにする

app/views/posts/_form.html.erb
<%= form_with(model: post, local: true) do |form| %>

<!--・・・省略・・・-->

  <%= form.label(:public, for: nil, class:'post-status__label') do %>
      <%= form.radio_button :status, :public %>
      <%= I18n.t('activerecord.attributes.post.statuses.public') %>
  <% end %>
  <%= form.label(:private, for: nil, class:'post-status__label') do %>
      <%= form.radio_button :status, :private %>
      <%= I18n.t('activerecord.attributes.post.statuses.private') %>
  <% end %>

<!--・・・省略・・・-->

<% end %>

公開・非公開を選択するUIは下記のようにしました。
この記事でははその実装手順はメイントピックではないので、割愛。
しかし、この実装に時間かかってしまった。

post_status.gif

選択した投稿ステータスを保存できるようにする

app/controllers/posts_controller.rb
class PostsController < ApplicationController

# ・・・省略

  def create
    @post = Post.new(post_params)
    @post.user_id = current_user.id

    respond_to do |format|
      if @post.save
        format.html { redirect_to @post, notice: '新規投稿を行いました。' }
        format.json { render :show, status: :created, location: @post }
      else
        format.html { render :new }
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end

# ・・・省略

  private

# ・・・省略

    def post_params
      params.require(:post).permit(
        :title,
        :content,
        :image,
        :status, # <= 追加:statusカラム
        {:cat_ids => []}
      )
    end

# ・・・省略

end


非公開記事一覧、詳細ページは、他のユーザーにアクセス時にはリダイレクトさせる

app/controllers/posts_controller.rb
class PostsController < ApplicationController
  before_action :set_post, only: [:show, :edit, :update, :destroy]

  # GET /posts/1
  # GET /posts/1.json
  def show

    if @post.status_private? && @post.user != current_user
      respond_to do |format|
        format.html { redirect_to posts_path, notice: 'このページにはアクセスできません' }
      end
    end

    # ・・・省略
  end

  # ・・・省略

  private
    def set_post
      @post = Post.find(params[:id])
    end

    # ・・・省略

end


記事一覧の取得方法

# 公開記事
$ Post.status_public.order(created_at: :desc).page(params[:page])

# 非公開記事
$ Post.status_private.order(created_at: :desc).page(params[:page])

# ランキング(Likeのトップ3)
$ Post.status_public.joins(:likes).group(:post_id).order('count(likes.post_id) desc').limit(3)


所要時間

作業内容 所要時間
見積 0.75H
実装・検証:新規投稿 7H
実装・検証:ユーザー詳細ページ 2.25H
実装・検証:投稿詳細ページ(localhost/posts/:id) 1H
実装・検証:記事一覧・詳細ページ(Like Ranking) 0.5H
実装・検証:記事一覧(localhost/posts) 0.125H
実装・検証:TOP(localhost) 0.125H
合計 12H

投稿編集ページを作るのに7Hかかってしまったので反省だが、なんとか作れたので良かったかな

さいごに

記事の公開・非公開機能追加の際にこの記事が参考になれば幸いです。

参考

【Rails】enumチュートリアル
Rails5 から enum 使う時は_prefix(接頭辞)_suffix(接尾辞)を使おう

25
19
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
25
19