LoginSignup
0
2

More than 3 years have passed since last update.

【Ruby on Rails】Rails Tutorialを全部終えたので、追加で「ストック機能」を実装してみた

Last updated at Posted at 2021-01-17

はじめに

Railsで「qiita」のような記事をストックする機能を実装したので、その方法を備忘録としてまとめておきます。
(基本的にはいいね機能と同じやり方)

※また、以下に記載する方法は前提として「Rails tutorial」を最後まで終えた程で記載させていただきます。

実装すること

・記事をストックするボタンを作成する。
・記事がどれくらいストックされているか表示する。
・ストックした投稿をストック一覧ページで確認できるようにする。

Stockモデルを作成する

ストック機能を実装するにあたって、最初のステップとしてStockモデルを作成します。

$ rails g model Stock

カラムは2つ作成します。
post_idカラム
user_idカラム
マイグレーションファイルは以下のように修正します。

xxxxxxxxxxxxx_create_stocks.rb
class CreateStocks < ActiveRecord::Migration[6.0]
  def change
    create_table :stocks do |t|
      t.references :user, foreign_key: true
      t.references :post, foreign_key: true

      t.timestamps
    end
    add_index :stocks, [:user_id, :post_id], unique: true
  end
end
$ rails db:migrate

2つのカラムは、それぞれ外部キーとして追加しておきます。
このテーブルは中間テーブルとして活用し、誰がどの投稿をストックしたかという情報を格納しておきます。
また、user_idカラムとpost_idカラムの組み合わせが一意になるようにインデックスを設定しておきます。

アソシエーションを設定する

以下のようにアソシエーションを設定します。
stock.rbにはアソシエーションのついでにバリデーションも追加しておきます。

user.rb

user.rb
has_many :stocks, dependent: :destroy

post.rb

post.rb
has_many :stocks, dependent: :destroy

stock.rb

stock.rb
belongs_to :user
belongs_to :post

validates :user_id, presence: true
validates :post_id, presence: true

stockコントローラを作成する

次にstockコントローラを作成します。

$ rails g controller Stocks

コントローラに処理を加える

stocks_controller.rb

stockコントローラを作成したら、今回の実装に必要なアクションを定義しておきます。

stocks_controller.rb
class StocksController < ApplicationController

  def create
    @stock = current_user.stocks.create(post_id: params[:post_id])
    redirect_back(fallback_location: root_path)
  end

  def destroy
    @stock = Stock.find_by(
      post_id: params[:post_id],
      user_id: current_user.id
      )
    @stock.destroy
    redirect_back(fallback_location: root_path)
  end

  def index
    @stocks = Stock.where(user_id: current_user.id)
  end
end

posts_controller.rb

次にpostコントローラshowアクションの部分に変数を追加します。
post/showページにストックボタンを表示する為です。

posts_controller.rb
  def show
    @post = Post.find_by(id: params[:id])
    @stock = Stock.find_by(
      user_id: current_user.id,
      post_id: @post.id
    )
  end

ルーティングを設定する

次に必要なルーティングを追加していきます。

routes.rb

routes.rb
resources :stocks, only:[:create, :destroy, :index]

今回はストックする機能(create)とストックを解除する機能(destroy)の他にストックした記事を表示する為の「index」も追加しておきます。

ストックしているかどうかの確認の処理と加える

ユーザーが記事に対して、すでにいストックをしているのかどうかを確認することができるようにstock?メソッドを定義しておきます。

user.rb

user.rb
  #ユーザーがすでにストックしているか確認する
  def stock?(post)
    self.stocks.exists?(post_id: post.id)
  end

Viewを追加&変更する

ストックボタンを実装する為に、まずはパーシャルを3つ作成していきます。

shared/_stock.html.erb

_stock.html.erb
<%= form_with(url:stocks_path, local: true) do |f| %>
  <div><%= hidden_field_tag :post_id, @post.id %></div>
 <%= f.submit "ストック", class:"btn-sm" %>
<% end %>

shared/_unstock.html.erb

_unstock.html.erb
<%= form_with(url: stock_path(@stock), html: {method: :delete}, local: true) do |f| %>
  <div><%= hidden_field_tag :post_id, @post.id %></div>
  <%= f.submit "ストックをやめる", class:"btn-sm" %>
<% end %>

shared/_stock_form.html.erb

_stock_form.html.erb
<% if current_user.stock?(@post) %>
  <%= render "shared/unstock" %>
<% else %>
  <%= render "shared/stock" %>
<% end %>
<%= @post.stocks.count %>

posts/show

ボタンを追加したいところに以下パーシャルを追加します。

show.html.erb
<%= render "shared/stock_form" %>

stocks/index.html.erb

indekページを新しく追加し、ストックした記事を表示させます。

index.html.erb
<h1>ストック一覧</h1>
<h2>あなたがストックしたポートフォリオの一覧です。</h2>

<% @stocks.each do |stock| %>
  <%= link_to stock.post.name, post_path(stock.post) %>
<% end %>

完成画

おわり

以上で終了です。
機能の実装方法を記述しているので、デザインは全く気にしていません。
デザインはお好みで付け足してみてください。

ソースコードはこちら

ポートフォリオ作成中のものですが。以下にあります。
https://github.com/iittaa/Sharing_Portfolio

0
2
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
2