【rails】「いいね」をcreateする

※本サイトで紹介している商品・サービス等の外部リンクには、アフィリエイト広告が含まれる場合があります。

ユーザーが記事に「いいね」できるのは1回

  • ユーザーは複数「いいね」する
  • 記事は複数「いいね」される

でも、1人のユーザーが1つの記事に「いいね」できるのは1回である

config/routes.rbを開く

  resources :articles do
    resources :comments, only: [:new, :create]

    resource :like, only: [:create]
  end

resource :likeは単数形になる

記事のidが指定できればいい(:destroyで詳しく説明)

「いいね」して、likesテーブルにレコードを作る
→ createPOSTリクエスト)になる


createアクションを定義する

app/controllers/likes_controller.rbを作成する

ログインしていることを前提とする

class LikesController < ApplicationController
  before_action :authenticate_user!

  def create
    article = Article.find(params[:article_id])
    article.likes.create!(user_id: current_user.id)
    redirect_to article_path(article)
  end
end

↓ :article_idが含まれているので、該当の記事をArticleから探してくる

  • article.likes.createできる理由
    → article.rbにて、has_many :likesを定義しているから.createができる
  • likesテーブルに必要なものは、article_iduser_idのみ
    → user_idcurrent_user.idだと渡してあげると、likesのレコードが作成できる
  • 「いいね」するだけなのに保存できなかった場合は絶対バグである
    → create!にしておけば、保存できないときはバグに気付ける
  • 「いいね」ができたら同じ画面article_pathredirect_toする


「いいね」ボタンを作成する

保存するときに使うのはarticle_like_path(POST)

app/views/articles/show.html.hamlを開く

  - if user_signed_in?
    .article_heart
      = link_to article_like_path(@article), data: { method: 'post' } do
        = image_tag 'heart.svg'
  1. もしログインユーザーが「いいね」していたら?(user_signed_in?
    → ’heart.svg’が表示される
  2. /articles/:article_id/like:article_idが含まれている
    → @articlearticle_like_pathに渡す
  3. link_toはデフォルトが「GET」リクエスト
    → それ以外のときはdata: { method: 'post' }のように書く

誰(ログインしている人)が、どの記事(@article)に「いいね」しているかが分かればいいので、コードはこれだけでok


「いいね」できているか確認する

コンソール画面を開く

User.first

User.first.likes
 # => <Like id: 1, user_id: 1, article_id: 1, ...

Article.find(1)

Article.find(1).likes
 # => <Like id: 1, user_id: 1, article_id: 1, ...

「いいね」できているので、Like id: 1が生まれている


「いいね」の有無で画像を切り替える

下記のように画像を切り替えるようにする

  • 「いいね」されていないとき→♡
  • 「いいね」されているとき→♥

「いいね」されているか定義する

app/models/user.rbを開く

そのarticleは「いいね」されているか?has_liked?

  def has_liked?(article)
    likes.exists?(article_id: article.id)
  end

likesのうち、article_idarticle.idと一致するlikeがあるか?exists?


定義したメソッドをview表示に使う

app/views/articles/show.html.hamlを開く

  - if user_signed_in?
    - if current_user.has_liked?(@article)
      .article_heart
        = image_tag 'heart-active.svg'
    - else
      .article_heart
        = link_to article_like_path(@article), data: { method: 'post' } do
          = image_tag 'heart.svg'
  • current_userが「いいね」していたら(has_liked?)、’heart-active.svg’を表示する
  • していなかったら、’heart.svg’を表示する

#DAY25