実装したいこと
- クチコミ投稿者以外がお気に入り登録をできる
- Ajax通信でお気に入り機能を実装
- マイページにお気に入り一覧を表示
目次
- お気に入りテーブルの作成
- アソシエーション
- ルーティング
- コントローラー
- ビュー
1. お気に入りテーブルの作成
どの投稿に、誰がお気に入りをしたのかを保存するために、お気に入りのテーブルを作成します。
ターミナル
rails g model like
class CreateLikes < ActiveRecord::Migration[6.0]
def change
create_table :likes do |t|
t.references :user, null: false, foreign_key: true
t.references :post, null: false, foreign_key: true
t.timestamps
t.index [:user_id, :post_id], unique: true # 同じユーザーが同じ投稿をお気に入りできないようにしている
end
end
end
2. アソシエーション
dependent: :destroyオプションを用いて、投稿が削除されたらお気に入りも削除されるようにします。親モデルに記述します。
class Like < ApplicationRecord
belongs_to :user
belongs_to :post
end
class Post < ApplicationRecord
belongs_to :user
has_many :likes, dependent: :destroy
has_one_attached :image
~略~
end
class User < ApplicationRecord
~略~
has_many :posts
has_many :likes
has_one_attached :image
end
3. ルーティング
どの投稿に対してのお気に入りかを示す必要があるので、ルーティングネストを用います。
お気に入りの登録と削除ができたら良いので、「createアクション」と「destroyアクション」を設定します。
Rails.application.routes.draw do
devise_for :users
root 'posts#top'
resources :posts do
collection do
get 'top'
end
resources :likes, only: [:create, :destroy]
end
resources :users, only: [:show]
end
4. コントローラー
コントローラーに「createアクション」と「destroyアクション」を定義します。
お気に入りの登録は投稿者以外が登録可能にしています。
class LikesController < ApplicationController
def create
@post = Post.find(params[:post_id])
if @post.user_id != current_user.id # 自分の投稿以外にお気に入り登録が可能
@like = Like.create(user_id: current_user.id, post_id: @post.id)
end
end
def destroy
@post = Post.find(params[:post_id])
@like = Like.find_by(user_id: current_user.id, post_id: @post.id)
@like.destroy
end
end
マイページにユーザーがお気に入り登録をした投稿を表示します。
Likesテーブルからログイン中のユーザーのお気に入りを検索し、降順に並べ、post_idを配列の形で取り出します。
それをfindメソッドで@likesにデータを格納しています。
class UsersController < ApplicationController
def show
@user = User.find(params[:id])
birthday = @user.birthday
date_format = "%Y%m%d"
@age = (Date.today.strftime(date_format).to_i - birthday.strftime(date_format).to_i) / 10000
@posts = @user.posts.order(created_at: :desc)
likes = Like.where(user_id: current_user.id).order(created_at: :desc).pluck(:post_id)
@likes = Post.find(likes)
end
end
5. ビュー
お気に入りボタンを表示する部分を部分テンプレートを作成して表示します。
if文でお気に入り登録している時としていない時で分岐しています。
~略~
<div class='star-btn' id="like_<%= @post.id %>">
<%= render "likes/like", post: @post %>
</div>
~略~
<% if !Like.exists?(user_id: current_user.id, post_id: post.id) %>
<%= link_to post_likes_path(post.id), method: :post, remote: true, class:"like-btn" do %>
<i class="fas fa-star star-icon1"></i>
<% end %>
<span class="star-count1"><%= post.likes.count %></span>
<% else %>
<%= link_to post_like_path(post_id: post.id, id: post.likes[0].id), method: :delete, remote: true, class:"like-btn" do %>
<i class="fas fa-star star-icon2"></i>
<% end %>
<span class="star-count2"><%= post.likes.count %></span>
<% end %>
お気に入りボタンがクリックされたときに「createアクション」または「destroyアクション」が実行され、部分テンプレートがAjax通信で更新されお気に入りボタンが表示されます。
※ jqueryで記述しているためインストールが必要です。
$('#like_<%= @post.id %>').html("<%= j(render partial: 'likes/like', locals: { post: @post }) %>");
$('#like_<%= @post.id %>').html("<%= j(render partial: 'likes/like', locals: { post: @post }) %>");
マイページのお気に入り一覧はeach文を用いて表示しています。
<% if @likes.present? %>
<ul class="relative-post-lists">
<% @likes.each do |like| %>
<li class='post-list'>
<%= link_to post_path(like.id) do %>
<div class='post-img-content'>
<%= image_tag like.image, class: "post-img" %>
</div>
<div class='relative-post-name'>
商品名:<%= like.name %>
</div>
<div class='relative-item-price'>
<span><%= like.price %>円(税込み)</span>
</div>
<div class="relative-post-evaluation">
<span>評価:</span>
<span id="star-rate-<%= like.id %>"></span>
<script>
$('#star-rate-<%= like.id %>').raty({
size: 36,
starOff: "<%= asset_path('star-off.png') %>",
starOn: "<%= asset_path('star-on.png') %>",
starHalf: "<%= asset_path('star-half.png') %>",
half: true,
readOnly: true,
score: <%= like.evaluation %>,
});
</script>
<%= like.evaluation %>
</div>
<div class='user-img-content'>
<%= image_tag like.user.image ,class:"mini-img" if like.user.image.attached? %>
<%= link_to like.user.nickname, user_path(like.user.id) %>
</div>
<div class="relative-post-date">
更新日時:<%= like.created_at.strftime("%Y.%m.%d") %>
</div>
<% end %>
</li>
<% end %>
</ul>
<% end %>
参考リンク
https://qiita.com/manbolila/items/43a04e8d0d5018cf7f62
https://qiita.com/naberina/items/c6b5c8d7756cb882fb20
https://qiita.com/naota7118/items/e009eff939b5a764672d