LoginSignup
2
1

More than 5 years have passed since last update.

railsでテーブルを使わないでいいね機能を作る(jquery>controller)

Last updated at Posted at 2018-07-25

railsでいいね機能を作るというと、
likeテーブルを作ってボタンを押される度にレコードを作成しているものが多いと思います。

今回は単純にレコードのlikeカラムを+1する方法で
いいね機能を実装しました。
wq9e2-mx7ou.gif

処理の流れ

  • divクリックをjqueryで感知
  • 要素のクラスを付け替え > 見た目を変える&再クリック防止
  • 数字を+1
  • ajaxでrailsコントローラの関数を呼ぶ
  • 関数内で+1する
  • 正常に終わった場合、コンソールログに”正常終了”と出す

本当はajaxが正常に終わった段階で
クラスの付け替え、数字の加算をしようとしたのですが、微妙にラグが出るのでやめました。

実装

DB構成

osusumes と novels が1対多で繋がっています。

おすすめという1ページにたくさんの小説情報がぶら下がり、
その小説情報のいいねが増えていく感じです。

アクセスして来たみんなが
「その小説いいよね!」といいねして、
いいね数で並び替え、人気の小説ほど上に来る
ということを実装したいと考えています。

画面の情報

osusumes#show画面に、
リレーションしているnovelsを表示しています。

コントローラ&ルーティング

osusumesの画面から飛ぶので、
osusumes_controllerにアクションを追加します。

osusumes_controller.rb
  def like
      # params[:id]の情報はajaxで送ります。
      @novel = Novel.find_by(id: params[:id])

      if @novel.like == nil
        @novel.update(like: 1)
      else
        @novel.update(like: @novel.like + 1)
      end
  end

追加したアクションを呼ぶルートを追加します。

routes.rb
Rails.application.routes.draw do
  get "osusumes/get_novel_info"
  #このosusumes/likeのルートを追加しました
  get "osusumes/like"
  resources :comments
  resources :novels
  resources :osusumes
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
  root "osusumes#index"
end

javascript(ajax)

application.js
$(document).on('turbolinks:load',function(){
  $(".novel-card-like").click(function(){
    //クラスの付け替え(クラスで見た目とクリック防止を実装)
    $(this).removeClass("fa-heart-o").addClass("fa-heart");
    //いいね数プラス1
    var old_like_count = parseInt($(this).find(".novel-like-count").text());
    $(this).find(".novel-like-count").text(old_like_count + 1);

    $.ajax({
        //osusumesの画面からurl likeを呼ぶことで、osusumes_controllerのlikeアクションを呼び出し
        url: "like",
        //novelのidをhtmlにhiddenパラメータで埋め込み
        //jqueryでidを取得してintegerに変換して送る
        data: { id : parseInt($(this).siblings(".novel-id").text()) },
        dataType: "html",
        //successをこの書き方すると、この中で$(this)が使える(今回は使わなかった)
        success: (data) => {
          console.log("正常にいいね完了")
        },
        error: function(data) {
          console.log('いいねをつけるのに失敗しています');
        }
    });
  });
});

参考URL : $(this) inside of AJAX success not working

scss

osusumes.scss
  .fa-heart-o{
    color: grey;
  }
  .fa-heart{
    color: red;
    //クリック防止
    pointer-events: none;
  }

html(haml)

_novel-card.haml
    .fa.fa-heart-o.novel-card-like
      %span{class: "novel-like-count"}
        - if novel.like != nil
          #{novel.like}
        - else
          0
    //novel.idを埋め込み
    .novel-id{style: "display:none"}
      #{novel.id}

課題

リロードすると何回でもいいね出来てしまう。
同じPC、ipアドレスからは1日1回のみいいね出来るとかそんな感じにしたいかも。

ipアドレステーブルみたいなのを作って、
ipアドレスとnovel.idを格納、
本日中のがあったらlike機能で足すのをやめるとかかな。。

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