1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Rails】いいね機能Ajax実装

Last updated at Posted at 2022-07-02

前提

  • Rails6
  • Devise実装
  • fontawesome導入
  • jQuery導入
  • いいね対象の投稿機能を実装

実装の流れ

  1. モデル作成・アソシエーション定義
  2. ルーティング設定
  3. コントローラー実装
  4. ビューの修正・追加

完成形

ezgif.com-gif-maker (3).gif

fontawesomeのアイコンを使用して、いいねボタンを実装しています

モデル作成・アソシエーションの定義

まずはモデルを作成していきます。今回、モデル名はLikeとします。
モデルのカラムにはどのユーザーがどの記事に対していいねをしたかを判別するために、
user_idとpost_idが必要になります。

rails g model Like user_id:integer post_id:integer
rails db:migrate
user.rb
  has_many :likes, dependent: :destroy
  has_many :like_posts, through: :likes, source: :post
post.rb
  has_many :likes, dependent: :destroy
  has_many :like_users, through: :likes, source: :user
like.rb
class Like < ApplicationRecord
  belongs_to :user
  belongs_to :portfolio
end

中間テーブル
has_many :中間テーブル名(任意)
through :経由するモデル名
source :関連付けの先のモデル名

ルーティング設定

ルーティングを以下のように設定します。
どの記事に属しているかを認識させたいのでPostsにネストさせます。

また、resourcesにすると不必要なパスまで生成されてしまうので、
resource単数形とonlyで指定することで必要なルーティングだけ生成させます。

routes.rb
  resource :posts do
    resources :likes, only: [:create, :destroy]
  end

スクリーンショット 2022-07-02 11.12.57.png
コントローラー実装

rails g controller likes create destroy
likes_controller.rb
class LikesController < ApplicationController
  before_action :set_post

  def create
    like = Like.new(user_id: current_user.id, post_id: @post.id)
    like.save
  end

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

  private

  def set_post
    @post = Post.find_by(id: params[:post_id])
  end

end

ビューの作成

ビューの必要なファイルを確認します。

views
├── likes
│   ├──_like.html.erb
│   ├──create.js.erb
│   └──destroy.js.erb
│ 
└── posts
    └──show.html.erb

流れ:
いいねアイコンをクリック

createアクションが実行され、create.js.erbをrender

パーシャル(_like.html.erb)を表示

いいねを外す時も同じ流れです。

記事詳細ページに「いいねボタンのパーシャル」を任意の位置に設置

views/posts/show.html.erb
 <div id="like_<%= @post.id %>">
  <%= render 'likes/like', post: @post %>
 </div>
  • jsを発火させるためにidを必ず指定します。 
  • パーシャル内(_like.html.erb)で記事のidが必要となるので、
    @postインスタンス変数をローカル変数postにして渡してあげます。

JavaScriptファイルを作成

create.js.erb
$('#like_<%=@post.id %>').html("<%= j(render "likes/like", post: @post) %>");
destroy.js.erb
$('#like_<%=@post.id %>').html("<%= j(render "likes/like", post: @post) %>");

html メソッドは、要素の HTML を取得したり 指定した HTML を挿入したりすることができるメソッドです。

パーシャルを作成

  1. ユーザーがログインしているかどうか確認
  2. ユーザーがログインしている場合、対象の記事をいいねしているかどうか確認
<% if user_signed_in? %>
  ユーザーがログインしている場合
   <% if current_user.likes.find_by(post_id: post.id) %>
       ユーザーが既に”いいね”をしている場合
   <% else %>
         ”いいね”をしていない場合
   <% end %> 
<% else %>
   ユーザーがログインしていない場合
    ▷いいねアイコンをクリックでログインページへ遷移
<% end %>

こうなります

_like.html.erb
<% if user_signed_in? %>
   <% if current_user.likes.find_by(post_id: post.id) %>
     <%= link_to post_likes_path(post.id), method: :DELETE, remote: true do %>
       <i class="fa fa-heart like_icon"></i>
     <% end %>
   <% else %>
      <%= link_to post_likes_path(post.id), method: :POST, remote: true do %>
        <i class="fa fa-heart unlike_icon"></i>
      <% end %>
   <% end %>
<% else %>
   <%= link_to new_user_session_path do %>
      <i class="fa fa-heart unlike_icon"></i>
   <% end %>
<% end %>

remote: :trueを忘れずに
link_toを非同期処理にする際は、remote: :trueを追加します。
デフォルトはfalseです。

css
.like_icon {
  font-size: 20px;
  color: #ff69b4;
}

.unlike_icon {
  font-size: 20px;
  color: #696969;
}

以上でいいね機能が実装できました!

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?