【Rails初心者】いいね機能追加まとめ

## _【Rails初心者】いいね機能追加まとめ_
いいね機能を追加する方法を自分なりにまとめてみた…

## いいね機能とは？
いいね!ボタン（英語: like button、like option、recommend button）とは、
好き/楽しい/支持できる といった意志を示すための機能である。

インターネットサービスにおいて通常コンテンツごとにこのボタンを押したユーザー数が表示され、
場合によっては押したユーザーのリストを全部もしくは一部表示できることもある。

これはコンテンツへの反応を表現する点で、レスを文章で書き込むといった他の方法に対し、定量的な代替手段である。

[wiki参照](https://ja.wikipedia.org/wiki/%E3%81%84%E3%81%84%E3%81%AD!%E3%83%9C%E3%82%BF%E3%83%B3)

## 必要なこと
- いいね機能に必要な DBの追加
- モデル作成
- モデルに関連付けを追加`
- Routing
- コントローラを作成
- View編集


## いいね機能を作成
### 1.いいね機能に必要なDBを確認する

| カラム名 | データ型 | カラムの説明 |
| :---: | :---: | :---: |
| id | integer | 「いいね」ごとのID |
| user_id | integer | 「いいね」したユーザのID |
| post_id | integer | 「いいね」された投稿のID |


### 2.以下のコマンドで、いいね機能に必要なDBを追加
~~~:Console
username:~/environment/hoge $ rails g model Favorite user_id:integer post_id:integer
~~~

マイグレーションでテーブルをデータベースへ反映させます。
~~~:Console
username:~/environment/meshiterro $ rails db:migrate
~~~

### 3.FavoriteModelにAssociationを追加
FavoriteModel が UserModel と PostMdelに属していることをfavorite.rbに記載

~~~ruby:app/models/favorite.rb
class Favorite < ApplicationRecord
  belongs_to :user
  belongs_to :post
end
~~~

### 4.PostModelにAssociationを追加する
PostModel が FavoriteModel をたくさん含む事をpost.rbに記載

~~~ruby:app/models/post.rb
class Post < ApplicationRecord

  has_many :favorites, dependent: :destroy
  :
  def favorited_by?(user)
    favorites.exists?(user_id: user.id)
  end
end
~~~

__Point__ 
- `def favorited_by?(user)`　[詳しくはこちらを参照](https://docs.ruby-lang.org/ja/3.1/doc/symref.html)
  - `favorited_by?`についてこの場合の「?」はメソッド名の一部分で、
   慣用的に、真偽値を返すタイプのメソッドを示すために使われる
  - 引数として`user` を `favorited_by?` が受け取る
- `favorites.exists?(user_id: user.id)`　[詳しくはこちらを参照](https://pikawaka.com/rails/exists)
  - `オブジェクト.exists?(条件)`
  - `exists?`メソッドとは、指定した条件のレコードがデータベースに存在するかどうかを真偽値で返すメソッド
    存在すればtrueを存在しなければfalseを返す

### 5.UserModelにAssociationを追加する
UserModel が FavoriteModel をたくさん含む事をuser.rbに記載

~~~ruby:app/models/user.rb
class User < ApplicationRecord
  has_many :favorites, dependent: :destroy  
end
~~~

### 6.Routingを追加する
configフォルダのroutes.rbファイルに追記
~~~ruby:app/models/user.rb
Rails.application.routes.draw do
  resources :posts, only: [:new, :create, :index, :show, :destroy] do
    resource :favorites, only: [:create, :destroy]    
  end
end
~~~

__Point__ 
- `resources~do~end`　[詳しくはこちらを参照](https://prograshi.com/framework/rails/nested_resources/)
  - ネストの定義をしている
  - resourcesをネストさせると、以下のような操作ができるようになる
  例1) １つの投稿（post）に対して複数のレビュー(favorite)を持たせる操作ができるようになる
  例2) １つの投稿（twiit）に対して複数のレビュー機能(いいね/コメント/retwiit)を持たせる操作ができるようになる
- `resources` `resource` の違い
  -  単数形にすると、/:idがURLに含まれなくなる
  -  いいね機能の場合は「1人のユーザーは1つの投稿に対して1回しかいいねできない」という仕様で、
     ユーザーidと投稿(post_image)idが分かれば、どのいいねを削除すればいいのかが特定できるので、いいねのidはURLに含める必要がない


### 7.FavoriteControllerを作成
favortes_controller.rbを作成
~~~:Console
username:~/environment/meshiterro $ rails g controller favorites
~~~

~~~ruby:app/controllers/favortes_controller.rb
class FavoritesController < ApplicationController

  def create
    post = Post.find(params[:post_id])
    #favorite = current_user.favorites.new(post_id: post.id)
    #favorite.save
    current_user.favorites.create(post_id: post.id)

    redirect_to post_path(post)
  end

  def destroy
    post = Post.find(params[:post_id])
    favorite = current_user.favorites.find_by(post_id: post.id)
    favorite.destroy
    redirect_to post_path(post)
  end

end
~~~
__Point__ 
- `favorites.create(post_id: post.id)`　[詳しくはこちらを参照](https://pikawaka.com/rails/create)
  - createメソッドとは、引数に渡されたデータを元にモデルのインスタンスを生成して、データベースに保存するメソッド
  - `モデル名.create({ カラム名: 値 })`
- `favorite.destroy`　[詳しくはこちらを参照](https://pikawaka.com/rails/destroy)
  - destroyメソッドとは、すでにテーブルに存在するレコードを削除するメソッド
  - `モデル名.create({ カラム名: 値 })`



### 8.app/views/postフォルダのshow.html.erbファイルを編集
favortes_controller.rbを作成
~~~:app/views/posts/show.html.erb
<div>
:
:
 <% if @post.favorited_by?(current_user) %>
    <p>
      <%= link_to post_favorites_path(@post), method: :delete do %>
        ♥<%= @post.favorites.count %> 
      <% end %>
    </p>
    <% else %>
    <p>
      <%= link_to post_favorites_path(@post), method: :post do %>
        ♡<%= @post.favorites.count %> 
      <% end %>
    </p>
  <% end %>
:
:
<div>
~~~
__Point__ 
- `if @post.favorited_by?(current_user)`
  - PostModelに記載した `favorited_by?`メソッドに`current_user`を引数として渡す
  - 処理内容としては、`@post`に紐づくuser_idが存在しているかの確認する
- `@post.favorites.count`　
  - `@post`に紐づく、favoritesDBのデータを数える


### 9.DBの確認
いいね機能が実行された際のDBを確認
~~~:Console DBコンソールの起動
username:~/environment/hoge $ rails dbconsole
~~~
~~~:Console sqlite3の出力モードを変更
sqlite> .mode line
~~~
~~~:Console 保存されているデータを出力
sqlite> select * from favorites;
~~~
post_idに紐づくデータが、追加されていることを確認
~~~:Console １回目いいねクリック時
        id = 1
   user_id = 2
   post_id = 8
created_at = 2022-09-04 10:40:11.074910
updated_at = 2022-09-04 10:40:11.074910

        id = 2
   user_id = 1
   post_id = 6
created_at = 2022-09-04 10:40:26.200083
updated_at = 2022-09-04 10:40:26.200083

        id = 3
   user_id = 1
   post_id = 8
created_at = 2022-09-04 10:40:45.717406
updated_at = 2022-09-04 10:40:45.717406
~~~
post_idに紐づくデータが、削除されていることを確認
~~~:Console ２回目いいねクリック時
        id = 1
   user_id = 2
   post_id = 8
created_at = 2022-09-04 10:40:11.074910
updated_at = 2022-09-04 10:40:11.074910

        id = 2
   user_id = 1
   post_id = 6
created_at = 2022-09-04 10:40:26.200083
updated_at = 2022-09-04 10:40:26.200083
~~~

クリックごとにいいねがついたり消えたりすれば成功です。お疲れさまでした！！
厳密には、FavoritesDBのデータが作成されたり、削除されていることが理解できたと思います！！


## まとめ
いいね機能を作成するには、新たにDB Model Controller の作成をおこない
ModelごとのAssociationをする必要がある！

見づらいや誤っている記載等あればコメント頂けると助かりますm(__)m

最終的には公式サイトから必要箇所を精査して、理解できるようになりたい！！

## 参考サイト
[Markdown記法 サンプル集 - Qiita](https://qiita.com/tbpgr/items/989c6badefff69377da7)
[Markdown記法 チートシート](https://qiita.com/Qiita/items/c686397e4a0f4f11683d)
[[Rails] dependent: :destroy について](https://qiita.com/Tsh-43879562/items/fbc968453a7063776637#%E7%B5%90%E8%AB%96)
[Rubyで使われる記号の意味（正規表現の複雑な記号は除く）](https://docs.ruby-lang.org/ja/3.1/doc/symref.html)
[【Rails】 resourcesメソッドを使ってルーティングを定義しよう！](https://pikawaka.com/rails/resources)
[【Rails】 createメソッドの使い方とは？new・saveメソッドとの違い](https://pikawaka.com/rails/create)
[【Rails】 destroyメソッドの使い方とは？](https://pikawaka.com/rails/destroy)
[【Ruby on Rails】DBの中身をコンソールで確認する](https://wild-outdoorlife.com/ruby-on-rails/rails-dbconsole/#toc3)