Ruby
RubyOnRails

いいね機能の実装と仕組み

今や当たり前のいいね機能

いいね機能がないwebサービスはかなり少ないと思います。。。
自分でwebアプリをつくっていると、どうしても取り入れたくなります。ですが、どのように実装するのかのやり方と、
仕組みの理解があまり自分なりに整理できていなかったので、まとめます。
最初にやり方、仕組みは下の方に書きますので、仕組みまで気になる方は是非。

※もちろん様々な仕組みがあるとは思いますが、自分が現時点で理解しているもので投稿します。

いいね機能実装

いいね機能の実装をMVCで書いていきます。
特定の食べものをいいねするという機能を作ります。

Model

food.rb
has_many :likes
has_many :users, through:likes
belongs_to :user

#特定のユーザーが特定のfoodをすでにいいねしているかを判別するメソッド
def liked? (like_user_id, like_food_id)
 likes.where(user_id: like_user_id, food_id: like_food_id).exists?
end
user.rb
has_many :likes
has_many :foods, through:likes
belongs_to :food

like.rb
belongs_to :food
belongs_to :user 

View

show.html.erb-food
#foodの一つ一つの個別ページでいいね数がどれくらいあるかをみれるようにする
<%= @food.likes.count%>

#すでにいいねされていれば、"いいねを消す"ボタン、いいねされていなければ"いいね"ボタンを出す
<% if @food.liked?(current_user.id, @food.id) %>
 <%= button_to 'いいねを消す', unlike_user_comic_path(user_id: current_user.id, id: @ food.id) %>
<% else %>
 <%= button_to 'いいね',like_user_comic_path(user_id: current_user.id, id: @food.id) %>
<% end %>

Controller

likes_controller.rb
#いいね機能
def create
 food_will_be_liked = Food.find(params[:id])
 food.likes.create(user_id: params[:user_id]) 
 redirect_to controller: "foods", action: "index"
end
#いいねを消す機能
def destroy
 food_will_be_unliked = Like.find(food.id: params[:id])
 food_will_be_unliked.delete
end
foods_controller.rb
#個別ページ出力メソッド
def show
@food = Food.find(params[:id])
end

コードとしてはこんな感じのはず。。。。
間違ってたら教えてください。。

いいね機能仕組み

一番最初に詰まったのは。。。。いいねという事実の表現

自分の中でいいね機能を作る際に詰まったのは、いいねしたという事実をどう表現するんだ?ってことです。。。(初心者なんですみません。)
likeテーブルに下のようなレコードが存在していれば、いいねをしたということになります。

スクリーンショット 2018-02-05 16.55.54.gif

上の図で言えば、2というuserは1というfoodと2というfoodにいいねをしていることになります。
3というユーザーは1というfoodにしかいいねしていませんね

特に重要だなと思ったメソッド

def liked?

まあこれは自分で作ったものなので、メソッド名はなんでも構いませんが。。。。
いいねしたかどうかを判別するというのもなかなか想像ができずに困っていましたが、上の事実表現が理解できれば簡単です。
要は上の例で言えば、food_idが1で、user_idが2のレコードが存在していればuser2はfood1をいいねしているといことになります。逆にdeleteしてしまえば このレコードが消滅するのでいいねはなかったことになります。

こんな形でいいね機能はできるはずです。