お気に入り機能を実装する


#はじめに
エンジニア転職のためポートフォリオを作成しているkazuです。
Railチュートリアルで作った制作物にいいね機能を実装しました！

Railsチュートリアルを一通り終えた方が読者の対象です。
#実装順序
1.ルーティング
２.モデルの設定
３.いいねの表示
４.コントローラの実装
##ルーティング
```ruby:config/routes.rb
  resources :microposts do
      resource :favorites, only: [:create, :destroy]
  end
```
ルーティングは以下のようになります。

```
micropost_favorites DELETE /microposts/:micropost_id/favorites(.:format)   favorites#destroy                                   
                    POST   /microposts/:micropost_id/favorites(.:format)   favorites#create                                            
```

##モデルの設定
###バリデーション
まずはデータベース側の設定、
次にモデルファイルを作ります。

```
rails g model Favorite user:references micropost:references
```

「 （モデル名） : references 」を付け足すと、モデルファイルに「belongs_to :micropost」が追加されます。
 その結果、user(micropost).favorite　といったメソッドチェーンが使えるようになります。
 　

```ruby:***_create_favorite.rb
class CreateFavorites < ActiveRecord::Migration[6.0]
  def change
    create_table :favorites do |t|
      t.references :user, null: false, foreign_key: true
      t.references :micropost, null: false, foreign_key: true

      t.timestamps
    end
    add_index :favorites, [:user_id, :micropost_id]
  end
end
```


```
rails db:migrate
```

マイグレーションファイルをデータベースに反映します。

```ruby:favorite.rb
class Favorite < ApplicationRecord
  belongs_to :user
  belongs_to :micropost

  validates :user_id, presence: true
  validates :micropost_id, presence: true
end
```

モデルのファイルは、こんな感じに。
##いいねボタンの表示
```html:app/views/home.html.erb
<% if current_user %>
  <div>
    <h2 class='top-micropost-title'>新着のメニュー</h2>
      <div class='top-micropost-wrapper new-wrapper'>
        <button id='new-scroll-left' class='scroll-btn new-scroll-btn'> { </button>
        <div class='top-micropost white-background slide' >
          <%= render partial: 'microposts/micropost', collection: @microposts %>
        </div>
        <button id='new-scroll-right'class='scroll-btn new-scroll-btn'> } </button>
      </div>
  </div>
<% end %>
```
「 render partial: 'microposts/micropost',collection: @microposts」 views/microposts/_micropost.html.erbをレンダリング。
collectionオプションで、配列の要素ごとに部分テンプレートが挿入されます。
今回は@micropostsの要素に対して、パーシャルが呼び出されます。

```html:app/views/microposts/_microposts.html.erb
<li id="micropost-<%= micropost.id %>">

  <span class="user"><%= link_to micropost.user.name, micropost.user %></span>
  <span class="title"><%= micropost.title %></span>
  <span class="content"><%= micropost.content %></span>
  <span class="timestamp">
     <%= time_ago_in_words(micropost.created_at) %>前
  </span>

  <div id="favorite_form">
    <%if !Favorite.exists?(user_id:current_user.id,post_id:post.id)%>
        <p><span><%= micropost.favorites.count %></span>
        <%= button_to 'お気に入り登録を削除', micropost_favorites_path(micropost_id: micropost.id), method: :delete %></p>
        <div><%= hidden_field_tag :favorite_id, micropost.id %></div>
    <% else %>
        <p><span><%= micropost.favorites.count %></span>
        <%= button_to 'お気に入り登録', micropost_favorites_path(micropost_id: micropost.id), method: :post %></p>
        <div><%= hidden_field_tag :favorite_id, micropost.id %></div>
    <% end %>
  </div>
</li>

```
「 if !Favorite.exists?(user_id:current_user.id,post_id:post.id) 」
投稿に対してお気に入り登録しているか確認します。

<%= button_to 'お気に入り登録を削除', micropost_favorites_path(micropost_id: micropost.id), method: :delete %></p><div><%= hidden_field_tag :favorite_id, micropost.id %></div>お気に入り登録を削除するリンクです。
link_toでは上手く行かなかったのでbutton_toで実装しています。詳しくは下の記事を参考にしてください。
https://qiita.com/mami3sansan/items/6a9710b3ffdc937aa5f3 (Railsでlink_to deleteメソッドが動かない)

##コントローラの実装
```ruby:app/controllers/favorites_controller.rb
class FavoritesController < ApplicationController
before_action :set_micropost
before_action :logged_in_user

  def create
    @favorite = Favorite.create(user_id: current_user.id, micropost_id: @micropost.id)
  end

   def destroy
    @favorite = Favorite.find_by(user_id: current_user.id, micropost_id: @micropost.id)
    @favorite.destroy
  end



  private

  def set_micropost
    @micropost = Micropost.find(params[:micropost_id])
  end
end

```
set_micropostでリンクに含まれているparams[:micropost_id]を@micropostに代入。
その後にcreateアクション、destroyアクションが動きます。