基礎編15

2021.3.26

課題15 ブックマーク機能の追加

 

参照

中間テーブルを使ったお気に入り機能の実装! - Ruby on Railsの備忘録

 

includesについて

【Rails】N+1問題をincludesメソッドで解決しよう! | Pikawaka - ピカ1わかりやすいプログラミング用語サイト

 

<ポイント>

 

 

❶同じユーザーが同じ掲示板に複数回ブックマークすることを防ぐ

(migrationファイル)

参照

add_index | Railsドキュメント

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

 

❷belongs_toオプションを設定すると、対象カラムに対するpresence: true は自動で設定される。

 

❸ユーザーと掲示板の組み合わせのレコードを一意にする

掲示板にお気に入り機能を実装する① - Ruby on Rails Learning Diary

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

ブックマークを外す処理は、ユーザーと掲示板のブックマークの関係性がなくなるように該当のレコードを削除する。もし、userとboardの組み合わせのレコードが重複すると、ブックマークを外しても関係性のレコードが残り、ブックマークが解除できなくなってしまう。

 

❹ユーザーがブックマークしている掲示板を取得するために

参照

Active Record の関連付け - Railsガイド

(user.rb)

has_many :bookmark_boards, through: :bookmarks, source: :board

twitterのいいね一覧のようにお気に入り登録した掲示板を一覧で常時できるページを作成するために必要。

has_many :bookmarks_boardsと定義することで、メソッド化して使うことができる。

Userのインスタンスにbookmarksメソッド(through:で定義)を実行し、それで得られたBookmarksのインスタンスデータのひとつひとつの要素に対してboardメソッド(source:で定義)を実行する

 

 

❺ブックマークする処理はモデルに寄せる

コントローラーに記載すると、可読性が落ちるため。

(user.rb)

def bookmark(board)
bookmark_boards << board ①
end

def unbookmark(board) ②
bookmark_boards.destroy(board)
end

def bookmark?(board)
bookmark_boards.include?(board)
end

① ブックマークする

<<メソッドは、1つ以上のオブジェクトを指定されたオブジェクトの末尾に破壊的に追加できる。このとき、追加されるオブジェクトの外部キーは、呼び出し側モデルの主キーに設定される。

<<で引数で渡した掲示板の情報がbookmarks_boardsに入ってる。
 
掲示板の情報のレコードが引数boardに格納され、bookmarks_boardsに
<<で追加されている。
強制的に追加、保存されるので、saveはいらない。
 
②ブックマーク外す
引数の中のboard_idが入ったレコードを探し、bookmark_boardsから
destroyする。
 
③ブックマークしているか判定する
 引数の中のboard_idが含まれているレコードがbookmarks_boardsにあるかどうか確認する。
 
 
 

破壊的メソッド: 処理失敗時に、例外をエラーとして返す
破壊的メソッドでない: 処理失敗時に、例外は発生させずに実行結果をfalseとして返す
.vaild? メソッドを実行したときと同様に、対象のオブジェクトのerrorsメソッドにバリデーションエラーの内容を登録する。

 

 

 

❼ GETリクエストでidを伴わないpathなので、collectionルーティングを使う。

参照

Nested Resource のルーティング、Member、Collection、Shallow の使いこなし - mabots' blog

(routes.eb)

resources :boards do
resources :comments, only: %i[create], shallow: true
collection do
get :bookmarks
end
end
resources :bookmarks, only: %i[create destroy]

resourcesで定義した時に作られる7つのアクションのほかにさらにアクションを追加したい時に使用する。

idが伴う場合はmemberルーティングを使用する。

今回は)

boards_controllerに新しくbookmarksというアクションを追加することができる。 

bookmarks_boards GET /boards/bookmarks(.:format)  boards#bookmarks

このようなルーティングが出来上がる。ブックマークされた掲示板一覧を表示するページとして使う。

後でBoards_controllerにbookmarksアクションを追加する。

 

 

redirect_backメソッド

redirect_back fallback_location: root_path, success: t('.success')

redirect_backはユーザーが直前にリクエストを送ったページに戻すことができる 。

fallback_locationは直前にリクエストを送ったページがない場合のデフォルトのリダイレクト先を指定している。