中級DAY25記事に「いいね」しよう + 記事にアイキャッチを設定しよう

![deitora_stady_header.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3870482/a8947be5-b1ce-b1a3-c1c0-adc2c9d7f363.png)


## 概要
**学習内容:** データベースのリレーション「n対n」の関係について学習し、特に「いいね」機能を実装するための設計方法を学びました。
* * *
## 学んだ主要な概念やスキル
~1. n対nのリレーションの理解~
複数のユーザーが複数の記事に「いいね」をする関係を実現するためには、n対nのリレーションを理解する必要がある。
例えば、ユーザー1が記事2と記事3に「いいね」し、ユーザー2が記事1に「いいね」するような場合など。


2. 中間テーブル（ライクステーブル）の役割
ユーザーと記事の関係を管理するために、中間テーブル（ライクステーブル）を作成する。
例えば、中間テーブルには、ユーザーIDと記事IDが格納され、これによってどのユーザーがどの記事に「いいね」したかが管理される。


3. アクティブレコードの設定
関連付けが必要、`has_manyとbelongs_to`の設定を使って、ユーザーと記事の間に「いいね」のリレーションを構築する。
デストロイの依存性についても、`dependent: :destroy`を設定することで、ユーザーや記事が削除された際に、それに関連する「いいね」も自動的に削除されるようにする。


4. データベースとアクティブレコードの連携

#### マイグレーションファイルの作成

`rails generate model`コマンドを使って、中間テーブルを含む必要なテーブルやモデルを作成する。

#### マイグレーションの実行

`rails db:migrate`コマンドでデータベースに反映させる。
![dots_line_rose.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3870482/d429fbf8-d43f-9b1e-bce2-1c72610de419.png)
## 01 Likeモデルを作ろう
## 使用したコード
**1. Likesテーブルのマイグレーションファイルの作成:**
```ruby:db > midrate > 20240826090536_create_likes.rb
create_table :likes do |t|
  t.references :user, null: false
  t.references :article, null: false

  t.timestamps
end
```

**2.モデルの設定:**

```ruby:app > models > user
has_many :likes, dependent: :destroy
```
```ruby:app > models > like.rb
 belongs_to :user
 belongs_to :article
```
```ruby:app > models > article.rb
has_many :likes, dependent: :destroy
```

![dots_line_rose.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3870482/d429fbf8-d43f-9b1e-bce2-1c72610de419.png)
# 02 「いいね」できるようになろう

### 〜手順の説明〜

**1. ルーティング設定:**

`config/routes.rb`で、記事に対する「いいね」のルーティングを設定。`resources :likes, only: [:create, :destroy]`とし、削除を考慮して`resources`を使用。
こうすることで、特定の`like_id`を指定せずに`like`を削除可能。

```ruby:config/routes.rb
  #いいねできるように生成・削除でハート画像が変わる
  resource :like, only: [:create, :destroy]
```


**2. コントローラーの作成:**
`LikesController`を作成し、`create`とd`estroy`アクションを定義。
`create`アクションでは、ログインしているユーザーと対象記事に基づいて「いいね」を作成。
`destroy`アクションでは、ユーザーが行った「いいね」を削除。

```ruby:app/controllers/likes_controller.rb
class LikesController < ApplicationController
    before_action :authenticate_user!
  
    def create
      article = Article.find(params[:article_id])
      article.likes.create!(user_id: current_user.id)
      redirect_to article_path(article)
    end

    def destroy
        article = Article.find(params[:article_id])
        like = article.likes.find_by!(user_id: current_user.id)
    
        like.destroy!
        redirect_to article_path(article)
      end



  end
```

**3. ビューの調整:**

記事の詳細ページで「いいね」ボタンを追加。ログインしているユーザーのみボタンが表示される。
`link_to`ヘルパーを使って、「いいね」ボタンをPOSTリクエストとして送信。
いいね済みかどうかに応じて、ボタンの表示を変更するために`User`モデルに`has_liked?`メソッドを追加。

```diff_ruby:app/views/articles/show.html.haml
- .article_heart
- = image_tag 'heart.svg'

+ - if user_signed_in?
+ - if current_user.has_liked?(@article)
+     .article_heart
+        = link_to article_like_path(@article), data: { method: 'delete' } do
+          = image_tag 'heart-active.svg'
+    - else
+     .article_heart
+        = link_to article_like_path(@article), data: { method: 'post' } do
+          = image_tag 'heart.svg'

```

**4. いいねの状態管理:**

ユーザーが既に「いいね」しているかどうかを確認し、している場合はボタンを赤色に変更。
いいねされている場合は、`has_liked?`メソッドを使って、`if`文で表示を切り替える。


**5. いいねの解除:**

いいねしたボタンを再度押すと、その「いいね」が解除されるように実装。


**6.最終確認:**

実際にブラウザ上で動作を確認し、いいねが正常に機能しているかを確認。


**7. セキュリティと利便性:**

`like_id`を直接操作せず、ユーザー自身が行った「いいね」だけを削除できるようにすることで、他のユーザーの「いいね」を誤って削除できないようにしている。

![dots_line_rose.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3870482/d429fbf8-d43f-9b1e-bce2-1c72610de419.png)

## 03.「いいね」の数を表示する
#### 「いいね」のカウント:
- 「いいね」の数をカウントするためには、`Rails`の`ActiveRecord`の`count`メソッドを使うと便利です。
- `likes.count`で、「いいね」の数を取得できます。
- 例えば、特定のアーティクルに対する「いいね」の数が1や0になる様子を確認することができます。

```rudy:models/article.rb
    def like_count
        likes.count
    end
```
```rudy:views/commons/_article.html.haml
        %span= article.like_count
```

#### アクションを定義:

```ruby:controllers/favories_controller
class FavoritesController < ApplicationController
    #ユーザーがログインしている状態か確認
    before_action :authenticate_user!
  
    def index
        #お気に入りした記事を取得
      @articles = current_user.favorite_articles
    end
  end
```


#### 自分が「いいね」した記事の表示:
- 自分が「いいね」した記事だけを表示するためのページを作成します。
- `has_many :through`の関連付けを使って、「いいね」した記事を取得します。
- モデル内で`has_many :favorited_articles, through: :likes, source: :article`と設定します。
- これにより、ログインユーザーが「いいね」した記事を取得し、表示することができます。
```rudy:models/user.rb
           #中間テーブルを通して自分がいいねした記事の情報を取得している
           has_many :favorite_articles, through: :likes, source: :article
``

#### ビューの作成:

- いいね」した記事を表示するビューを作成します。
- `app/views/favorites/index.html.erb`に表示する内容を記述し、ユーザーが「いいね」した記事の一覧を表示します。
- リンクを追加して、他のページと連携するようにします。
```ruby:views/favorites/index.html.haml
.container
  %h2
    お気に入りの記事
  - @articles.each do |article|
    = render 'commons/article', article: article
```
#### ついでにロゴURLをつける

```diff_ruby:views/layouts/application.html.haml
-       %p.header_pageTitle B-log-app
+       %p.header_pageTitle
+          = link_to 'BlogApp', root_path
```


![dots_line_rose.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3870482/d429fbf8-d43f-9b1e-bce2-1c72610de419.png)
## 05.アイキャッチの設定
😺 　さあ、この日最後の授業だにゃん！
🦊 　やっていいこう！

画像のアップロードと表示の機能を追加する手順が解説されました。

#### Active Storageの復習と設定:

まず、アーティクルモデルで画像アップロード機能を追加します。画像を1つだけアップロードする場合は`has_one_attached`を、複数の場合は`has_many_attached`を使用します。
#### コントローラーの設定:

アーティクルコントローラーで、画像を許可するパラメーターを設定します。
#### ビューの設定:

ビューでフォームにファイルアップロード用のフィールドを追加し、ユーザーが画像をアップロードできるようにします。
#### 画像の表示:

アップロードされた画像を表示するためのコードを追加します。詳細ページ（ショーアクション）でも画像が表示されるようにし、画像が大きすぎる場合はCSSでサイズを調整します。
#### 動作確認:

画像のアップロードが正しく機能しているかを確認し、新規作成や編集時にも画像が表示されることを確認します。
#### 次回予告:

次回は、このアプリケーションを公開するための準備について説明する予定です。

# お疲れ様でした！