1日1%成長するブログ

毎日成長するために仕事/プライベートで得た学びをアウトプットするブログです

Rails5でajaxを使っていいね機能を実装する

ルーティングを用意する

resources :diaries do
  resources :diary_comments, only: [:create]
  resources :diary_likes, only: [:create, :destroy]
end
  • diaryが重複するので後でスッキリさせる

モデルを用意する

class Diary < ApplicationRecord
  belongs_to :user
  has_many :diary_likes, dependent: :destroy

  # ユーザーのいいねを取得
  def like(user_id)
    diary_likes.find_by(user_id: user_id)
  end
end

部分テンプレートを用意する

<% if diary.like(user.id) %>
  <button class="btn btn-default btn-xs disabled" type="button">
    <i class="fa fa-thumbs-o-up">いいね済み</i>
  </button>
<% else %>
  <button class="btn btn-default btn-xs" type="button">
    <i class="fa fa-thumbs-o-up">いいね</i>
  </button>
<% end %>
<% else %>

button_toに書き換える

 <%= button_to diary_likes_path(diary), remote: true, class: "btn btn-default btn-xs" do %>
   <i class="fa fa-thumbs-o-up">いいね</i>
 <% end %>
  • button_toは実際にはformとbuttonタグとして出力される。こんな感じ
<form class="button_to" method="post" action="/diaries/1/likes" data-remote="true"
    <button class="btn btn-default btn-xs" type="submit">
      <i class="fa fa-thumbs-o-up">いいね</i>
    </button>
    <input type="hidden" name="authenticity_token" value="xx">
</form>
<% if diary.like(user_id) %>
  <%= button_to diary_diary_like_path(diary, diary.like(user_id)), remote: true, method: :delete, class: "btn btn-default btn-xs" do %>
    <i class="fa fa-thumbs-o-up">いいね済み</i>
  <% end %>
<% else %>
  <%= button_to diary_diary_likes_path(diary), remote: true, class: "btn btn-default btn-xs" do %>
    <i class="fa fa-thumbs-o-up">いいね</i>
  <% end %>
<% end %>
<% else %>

いいねボタンを用意

.like-button{:class => "like-button-#{diary.id}"}
  = render "diary_likes/like", diary: diary, user_id: diary.user_id
  • 日記ごとに部分テンプレート化したいいね!ボタンをrenderする

いいね機能を実装する

def create
  @like = DiaryLike.new(user_id: current_user.id, diary_id: params[:diary_id])
  @like.save
end

def destroy
  @like = DiaryLike.find_by(user_id: current_user.id, diary_id: params[:diary_id])
  @like.destroy
end
  • diary_idしか送られてこない & そのまま保存するわけでもないのでストロングパラメータは不要
  • remote: trueで送っているので、xxx.js.erbが呼ばれる

create.js.erbを作成

$(".like-button-<%= @like.diary_id %>").html("<%= j(render partial: 'like', locals: { diary: @like.diary, user_id: @like.user_id }) %>")

destroy.js.erbを作成

$(".like-button-<%= @like.diary_id %>").html("<%= j(render partial: 'like', locals: { diary: @like.diary, user_id: @like.user_id }) %>")