めちゃ手こずったAjax　いいね機能作成、、メモ書きとして。Ruby on rails6.0.0

どうもこんにちは、

今回は、僕がとても手こずった機能である
<h1> いいね機能<h1>

について紹介します👍

いろんな記事を参考に進めたのですが、
なかなかうまく行かなかったので、記録として残しておき、
後世に語り継ぎたいと思います。（大げさ）


<br/>

では早速やっていきましょう！


この記事は以下の情報を参考にして執筆しました。

- [【Rails×Ajax】いいね機能ハンズオン](https://qiita.com/naberina/items/c6b5c8d7756cb882fb20)
- [【Rails】ブックマーク機能のajax化](https://qiita.com/hiro266/items/ef860435021faa3f96b5)



まず


```
% rails g model Favorite user_id:integer book_id:integer

```
マイグレーションファイルに記述します

```favorite.rb
class CreateFavorites < ActiveRecord::Migration[6.0]
  def change
    create_table :favorites do |t|
      t.integer :user_id
      t.integer :book_id

      t.timestamps
      t.index [:user_id, :book_id], unique: true　これで一意性をつけている　
    end
  end
end
```
t.indexについては[stackoverflow](https://stackoverflow.com/questions/21635825/how-to-create-a-new-table-with-a-unique-index-in-an-active-record-rails-4-migr)に詳しく話しているのがあります

そして忘れずに

```
$ rails db:migrate
```

お次はこれらを追加

``` favorite.rb
class Favorite < ApplicationRecord
  belongs_to :user
  belongs_to :book
end
```

```book.rb

  belongs_to :user
  has_many :users, through: :favorites　throughでbookとuserをつないでます
  has_many :favorites 


*1
  def favorited_by?(user)
    favorites.where(user_id: user.id).exists?
  end
```


```user.rb

         has_many :books
         has_many :favorites 
         has_many :favorite_books, through: :favorites, source: :book  同じく
```


そして、
*１に関しては、この後使うので少々お待ち下さい
今はメソッドを生成しているとだけご理解ください。



次にビューとコントローラーを作っていきます

```
 % rails generate controller favorites create destroy
```

最後にcreate destroyと付け足すことで
この二つのビューだけ作ってくれます


```favorites/_favorite.heml.erb

<div class="favorite-button">
 <% if user_signed_in? %>
  <% if book.favorited_by?(current_user) %>
   <%=link_to "💔 #{book.favorites.count}",book_favorites_path(book.id), method: :delete, class: 'btn btn-default', remote: true %>　
    <% else %>
   <%= link_to "💖 #{book.favorites.count}", book_favorites_path(book.id), method: :post, class: 'btn btn-default', remote: true %>   
   <% end %>
  <% else %>
    <button><span>お気に入り数: </span><%= book.favorites.count %>
  <% end %>
</div>


```
_favoriteとわざわざ切り出してるのは、可読性を上げるため？
とAjax化のためだそうです

remote tureをつけ忘れるとAjax化できなくなるそうです
remote tureをつけると
リクエストがhtml形式ではなくjs形式になる！
とこの記事では書かれています
[remote true参考記事](https://qiita.com/__tambo__/items/45211df065e0c037d032)


```favorites/create.js.erb
$('#favorites_buttons_<%= @book.id %>').html("<%= j(render partial: 'favorites/favorite', locals: {book: @book}) %>");

```
```favorites/destroy.js.erb
$('#favorites_buttons_<%= @book.id %>').html("<%= j(render partial: 'favorites/favorite', locals: {book: @book}) %>");

```

そしていいねボタンを作りたいところにこれ！！！！！

```
    <div class="like">
        <%# いいね %>
          <div id="favorites_buttons_<%= @book.id %>">
            <%= render partial: 'favorites/favorite', locals: { book: @book } %>
          </div>
        <%# いいね %>
```

render の後は呼び出したいファルダ名（ディレクトリ名）を指定

id はボタンを押したとき反応してくれるところなので忘れずに記入記入

```favorites_controller.rb
class FavoritesController < ApplicationController
  def create
    @book = Book.find(params[:book_id])
    @favorite = current_user.favorites.build(book_id: params[:book_id])
    @favorite.save
  end

  def destroy
    @book = Book.find(params[:book_id])
    @favorite = Favorite.find_by(book_id: params[:book_id], user_id: current_user.id)
    @favorite.destroy
  end
end

```


コントローラーはこんな感じ。
僕、前ここにriderect_toをつけていたせいで
思うように動かなかったんですよね。。

本来Ajax化のために
favorites/create.js.erb
に飛んで処理が実行されなきゃいけないんですけど
redirect_toが邪魔してました、、



こんな感じでできあがりです！！


いかがだったでしょうか。

これで実装できなったら、バージョンなどを確認して見てください。
バージョン違うだけで結構変わるらしいので！
｛僕もそれでハマりました。）



ちなみに今回はバージョンRuby 6.0.0です