はじめに
先日、いいね機能を実装した。↓
showテンプレートにいいねしたユーザー一覧を表示するようにしていたが、indexテンプレートを実装するよう変更する。
その際にroutes.rbでresource=>resourcesに変更した。
これにより、ルーティングの変更が発生するため、その修正すべき部分を解説していく。
前提
下記のテーブルは作成済み。
users(ユーザー)
posts(投稿)
favorites(いいね)
No | 項目 | 内容 |
---|---|---|
1 | OS | Mac |
2 | Ruby | 2.6.3 |
3 | rails | 6.0.4 |
ルーティングを修正する
indexを追加するために、resouceをresourcesに変更する。
resource:
・index以外のRESTに準拠したルーティングを生成できる。
・pathはidを含める必要がない。
resources:
・indexを含む全てのRESTに準拠したルーティングを生成できる。
・:edit, :show, :update, :destroyアクションの pathにidを含める必要がある。
# resources :posts do
# resource :favorites, only: [:show, :create, :destroy]
# 下記に変更
resources :posts do
resources :favorites, only: [:index, :create, :destroy]
$ rails routes
# ルーティング変更前
# post_favorites GET /posts/:post_id/favorites(.:format) favorites#show
# DELETE /posts/:post_id/favorites(.:format) favorites#destroy
# POST /posts/:post_id/favorites(.:format) favorites#create
# ルーティング変更後 (showとdestroyが「post_favorite_path」になったことに注意)
post_favorites GET /posts/:post_id/favorites(.:format) favorites#index
POST /posts/:post_id/favorites(.:format) favorites#create
post_favorite DELETE /posts/:post_id/favorites/:id(.:format) favorites#destroy
これでindexを作成可能となり、destroyアクションでfavoriteテーブルの:idが必要となる。
いいね機能周りの修正
いいね取り消し(destroy)で@favoriteが必要となる。
いいねをすると、次に取り消しボタンが表示されるため、そこで@favorite
が必要になる。よって、createアクションに実装する。
def index
@post = Post.find(params[:post_id])
@favorite_users = @post.favorite_users
end
# favorite をインスタンス変数@favoriteに修正した。
def create
@post = Post.find(params[:post_id])
@favorite = current_user.favorites.create(post_id: @post.id)
@favorite.save
@favorite_users = @post.favorite_users
respond_to do |format|
format.html { redirect_to @post }
format.js
end
いいねを押した時に反応したjsファイルを修正する。
# favorite: @favoriteを追加する
$("#favorite_icon_<%= @post.id %>").html("<%= escape_javascript(render('favorites/favorited_state', post: @post, favorite: @favorite)) %>");
いいねを押した後に、上記によりレンダリングされるパーシャルを修正する。
いいねを押した後はいいね取り消しのための情報が必要である。
取り消しには、favoriteテーブルの該当idを取得し、それを使ってdeleteリクエストを投げればよい。
# post_favorite_pathに修正と、favorite.idを追加
<%= link_to post_favorite_path(post.id, favorite.ids), class: "btn", method: :delete, remote: true do %>
<i class="fa-solid fa-thumbs-up fa-3x"></i>
<% end %>
投稿機能周りの修正
favoriteの:id情報を取り込む。
投稿記事のshowコントローラーと、showページに@favoriteを追加する。
def show
@post = Post.find(params[:id])
# 下記を追加
@favorite = Favorite.find_by(post_id: @post.id)
...
end
...
<%# いいね機能 %>
<span id="favorite_icon_<%= @post.id %>">
<% unless current_user?(@user) %>
<% if @post.favorited?(current_user) %>
# @favoriteを追加
<%= render 'favorites/favorited_state', post: @post, favorite: @favorite %>
<% else %>
# @favoriteを追加
<%= render 'favorites/unfavorited_state', post: @post, favorite: @favorite %>
<% end %>
<% end %>
</span>
...
<%= link_to "いいねしたユーザー", post_favorites_path(@post) %>
# => app/views/favorites/index.html.erb
...
いいねしたユーザー一覧のindexテンプレートを作成する
index.html.erbを作成し、内容を書いていく。(show.html.erbに書いてた内容を移すだけ。)
<ol id="favorite_user">
<%= render partial: 'favorites/favorite_user', favorite_users: @favorite_users %>
</ol>
<%= link_to :back do %>
<button class="btn margin-top">BACK</button>
<% end %>
完成
おわりに
resource を resources に変更するだけで、かなりの工数を使った。
基本的には、indexをつくる気がなくても、resourcesでルーティングを書いた方がいいのかもしれない。
pathに対して、idを渡す必要が出てきてしまうが、そこはトレードオフになる。