LoginSignup
2
1

More than 1 year has passed since last update.

[Rails] ブックマーク機能の実装

Posted at

はじめに

ブックマークを実装するための忘備録です。

実行環境

  • Rails 5.2.3
  • Ruby 2.6.4

実装

1. アソシエーション

bookmark.png

中間テーブルとしてbookmarksテーブルを作成。

2. モデル

2.1 モデルの作成

$ rails g model Bookmark user:references board:references

マイグレーションファイルに追記をします。

db/migrate
class CreateBookmarks < ActiveRecord::Migration[5.2]
  def change
    create_table :bookmarks do |t|
      t.references :user, foreign_key: true
      t.references :board, foreign_key: true

      t.timestamps
    end

    add_index :bookmarks, [:user_id, :board_id], unique: true
  end
end

重複を防ぐために、複合キーインデックスを使い、unique:trueとします。
データベースへ反映させます。

$ rails db:migrate

2.2 モデルの関連付け

app/model/bookmark.rb
class Bookmark < ApplicationRecord
  belongs_to :user
  belongs_to :board

  validates :user_id, uniqueness: { scope: :board_id }
end

モデルのバリデーションでも重複を防ぐために、scopeを使ってuniquness制約をつくります。

app/model/user.rb
class User < ApplicationRecord
  .
  .
  has_many :bookmarks, dependent: :destroy
  .
  .

end
app/model/board.rb
class Board < ApplicationRecord
  .
  .
  has_many :bookmarks, dependent: :destroy

  def bookmarked_by?(user)
    bookmarks.where(user_id: user).exists?
  end
end

ブックマークが既にされているかのメソッドをモデルにbookmarked_by?(user)として定義します。

3. コントローラーの作成

$ rails g controller bookmarks
app/controllers/bookmark_controller.rb
 class BookmarksController < ApplicationController
  def create
    board = Board.find(params[:board_id])
    bookmark = board.bookmarks.build(user_id: current_user.id)
    if bookmark.save
      redirect_to request.referer
    else
      redirect_to request.referer
    end
  end

  def destroy
    board = current_user.boards.find(params[:board_id])
    bookmark = board.bookmarks.find_by(user_id: current_user.id)
    if bookmark.present?
      bookmark.destroy
      redirect_to request.referer
    else
      redirect_to request.referer
    end
  end
end

3. ルーティングとビューの作成

config/routes.rb
  resources :boards do
    resource :bookmarks, only: %i[create destroy]
  end
  
app/views/board/index.html.erb
  <% if board.bookmarked_by?(current_user) %>
    <%= link_to "ブックマーク", board_bookmarks_path(board), method: :post %>
  <% else %>
    <%= link_to "ブックマークを外す", board_bookmarks_path(@board), method: :delete %>
  <% end %>

参考にさせていただいた記事

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