LoginSignup
3
4

More than 1 year has passed since last update.

【Rails】いいね機能の実装(非同期)

Posted at

目的

Railsで作成したアプリに非同期いいね機能を実装する。

開発環境

macOS: Big Sur
Rubyバージョン: 2.6.5
Railsバージョン: 6.0.0

前提

手順

  1. はじめに
  2. ルーティングの設定
  3. Likeモデルの作成
  4. アソシエーションの設定
  5. バリデーションの設定
  6. メソッドの定義
  7. likesコントローラーの作成
  8. アクションの定義
  9. いいねアイコンの表示
  10. jsファイルの作成

はじめに

今回は非同期でのいいね機能を実装していきます。
工程は多いですが、やっていることは複雑ではないため、初学者さんでもしっかり読めばできる内容かと思います。

ルーティングの設定

それでは早速始めていきます!

まずルーティングをネストさせ、設定します!

routes.rb
Rails.application.routes.draw do
#省略
  resources :posts, do
    resources :likes, only: [:create, :destroy]
  end
end

Likeモデルの作成

次に下記コマンドでLikeモデルを作成します。

ターミナル
% rails g model like

今回はどの投稿に誰がいいねしたかを記録したいので、user_idpost_idをカラムに追加します。

db/migrate/20XXXXXXXXXXXX_create_likes.rb
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
    end
  end
end

記述できたらマイグレートします。

ターミナル
% rails db:migrate

以上でモデルは完成です!

アソシエーションの設定

続いてアソシエーションの設定です。

app/models/user.rb
class User < ApplicationRecord
#省略
  has_many :likes, dependent: :destroy
  has_many :liked_posts, through: :likes, source: :post
end
app/models/post.rb
class Post < ApplicationRecord
#省略
  has_many :likes, dependent: :destroy
  has_many :liked_users, through: :likes, source: :user
end
app/models/like.rb
class Post < ApplicationRecord
#省略
  belongs_to :user
  belongs_to :post
end

これでアソシエーションの設定ができました!

バリデーションの設定

次はバリデーションの設定です。
1人が1つの投稿に対して、1つしかいいねをつけられないようにします。

app/models/like.rb
class Like < ApplicationRecord
#省略
  validates_uniqueness_of :post_id, scope: :user_id
end

validates_uniqueness_ofによって、post_iduser_id の組は1組しかできないようになりました。

メソッドの定義

いいねしているか否かという条件分岐の際に使用するメソッドを定義します。

app/models/user.rb
# 省略

  def liked_by?(post_id)
    likes.where(post_id: post_id).exists?
  end
end

whereメソッドを使用し、likesテーブルにpost_idが存在しているかどうか検索をかけています。
exists?メソッドは、該当の値があればtrue、なければfalseを返すメソッドです。

likesコントローラーの作成

コントローラーを作成します。

ターミナル
% rails g controller likes

アクションの定義

次にアクションの定義です。

likes_controller.rb
class LikesController < ApplicationController
  before_action :authenticate_user!, only: [:create, :destroy]
  before_action :post_params, only: [:create, :destroy]

  def create
    Like.create(user_id: current_user.id, post_id: @post.id)
  end

  def destroy
    like = Like.find_by(user_id: current_user.id, post_id: @post.id)
    like.destroy
  end

  private
  def post_params
    @post = Post.find(params[:post_id])
  end
end

createdestroyアクションを定義していきます。

find_byメソッドは、複数の検索条件を指定することができるメソッドです。

いいねアイコンの表示

次に部分テンプレートを切り替える部分にidを付与します!
具体的には「id = "like_<%= @post.id %>"」と記述することで、投稿それぞれ異なるidを付与します。

app/views/posts/show.html.erb
<div id = "like_<%= @post.id %>">
  <%= render partial: "likes/like", locals: { post: @post } %>
</div>

部分テンプレートです。

app/views/likes/_like.html.erb
<% if !user_signed_in? %>
  <i class="fa fa-heart like-btn"></i>
  <%= post.likes.length %>
<% elsif current_user.liked_by?(post.id) %>
  <%= link_to post_like_path(post, post.likes), class: "like-link", method: :delete, remote: true do %>
    <i class="fa fa-heart unlike-btn"></i>
  <% end %>
  <%= post.likes.length %>
<% else %>
  <%= link_to post_likes_path(post), class: "like-link", method: :post, remote: true do %>
    <i class="fa fa-heart like-btn"></i>
  <% end %>
  <%= post.likes.length %>
<% end %>

remote: trueを付与することでパラメーターをJS形式で送られ、createアクション後は、create.js.erbが呼び出されます。

app/assets/stylesheets/likes.scss
.like-link {
  text-decoration: none;
}

.like-btn {
  font-size: 1em;
  color: #808080;
}

.unlike-btn {
  font-size: 1em;
  color: #e54747;
}

いいねした時いいねしていない時で色を変えまてます。

jsファイルの作成

いいね機能を非同期で行うためのjsファイルを作成します。

app/views/likes/creste.js.erb
$('#like_<%= @post.id %>').html("<%= j(render partial: 'likes/like', locals: { post: @post }) %>");
app/views/likes/destroy.js.erb
$('#like_<%= @post.id %>').html("<%= j(render partial: 'likes/like', locals: { post: @post }) %>");

これで非同期でのいいね機能が実装できたと思います。
確認してみてください!

最後に

以上で、いいね機能の実装は完了です。
長くなってしまいましたが、一つ一つ理解していけば実装できると思いますので、ぜひ試してみてください。
では。

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4