実装イメージ
https://desolate-peak-43756.herokuapp.com/
適当に会員登録をして、ログインをしてください。
#github
https://github.com/a-itabashi/InstagramClone
ソースコードはこちらで確認してください。
環境
ruby 2.6.2
Rails 5.2.3
psql (PostgreSQL) 11.2
テーブル構成(アソシエーション)の確認
※まずは、実装後のUIと上のER図を常に念頭に置く。
モデルの定義
app/models/user.rb
has_many :posts
has_many :favorites, dependent: :destroy
app/models/favorite.rb
belongs_to :user
belongs_to :post
app/models/post.rb
belongs_to :user
has_many :favorites, dependent: :destroy
has_many :favorite_users, through: :favorites, source: :user
throughオプションを使うことにより、今後、レコードの取得が容易になる。
今回は、任意のpost.idと一致するuserの情報を取得したいので、
favorite_usersメソッドを定義している。
※メソッド名は、自分で好き勝手につけて良いが、分かりやすい物を
※sources: :userのuserは、favoriteモデルで定義した、
belongs_to :user
のuserに起因する。
config/routes.rb
resources :users
resources :posts
resources :favorites, only:[:create, :destroy]
今回は、ブログの詳細ページ先(app/views/posts/show.html.erb)にお気に入りボタンを配置する。
※ヘルバーメソッドとして、current_user(ログイン中のユーザーを取得し、インスタンス変数:@current_userを返すメソッド)を定義している前提で進めます。
app/controllers/posts_controller.rb
def show
@favorite = current_user.favorites.find_by(post_id: @post.id)
@favorites= @post.favorite_users
end
@favoriteでログイン中のユーザがお気に入りしている全投稿の中で、特定の投稿(post_id)を取得
@favoritesで特定の投稿に対して、お気に入りをしている全ユーザーを取得(先のthroughオプションで定義したメソッドを使用)
app/views/posts/show.html.erb
<% unless @post.user_id == current_user.id %>
<% if @favorite.present? %>
<h2>この投稿のお気に入りを解除しますか?<h2>
<div class="like-btn">
<%= link_to "解除する", favorite_path(id: @favorite.id), method: :delete, class: "btn btn-danger" %>
</div>
<% else %>
<h2>この投稿のお気に入りに登録しますか?<h2>
<div class="like-btn">
<%= link_to "登録をする", favorites_path(post_id: @post.id), method: :post, class:"btn btn-primary like-btn" %>
</div>
<% end %>
<% end %>
 
<h1>この投稿をお気に入りしたユーザー一覧</h1>
<% @favorites.each do |favorite| %>
<%= image_tag(favorite.user_image,class: "member-img") if favorite.user_image && favorite.user_image.url %>
<%= favorite.name %>
<% end %>
app/controllers/favorites_controller.rb
class FavoritesController < ApplicationController
def create
favorite = current_user.favorites.create(post_id: params[:post_id])
flash[:success] = "この投稿をお気に入りに登録しました"
redirect_to post_path(favorite.post.id)
end
def destroy
favorite = current_user.favorites.find_by(id: params[:id]).destroy
flash[:danger] = "この投稿のお気に入りを解除しました"
redirect_to post_path(favorite.post.id)
end
end
コントローラーに渡すパラメーター(post_idなどの引数)を意識することが重要。