【Rails】Railsでタグ付け機能を実装した時のメモ。

#はじめに
掲示板やブログ等のアプリの投稿フォームで、タグのチェックボックスを選択し、表示する機能を作成します。
今回はgemの` acts-as-taggable-on `は使用せずに実装してみたいと思います。



#バージョン
- ruby 2.6.3
- rails 6.0.1
- mysql 8.0.18

#前提
- Rails環境構築済みであること

#モデルの作成
まず、今回作成するするモデルは以下の３つになります。

|Articles|Article_tag_relations|Tags| 
|---|---|---|     
|id|id|id|
|title|article_id|name
|body|tag_id|

- Articles
    - 掲示板の記事に関するテーブル
- Tags
    - タグに関するテーブル
- Article_tag_relations 
    - 掲示板とタグを紐づけるための中間テーブル

では、さっそくモデルを作成していきます。

```
#Articleモデルのマイグレーションファイル生成
$rails g model Article title:string body:string

#Tagモデルにマイグレーションファイル生成
$rails g model Tag name:string

#Article_tag_relationモデルのマイグレーションファイル生成
$rails g model Article_tag_relation article:references tag:references
```

今回はTagsテーブルのnameカラムにはnullを許容しないので、マイグレーションファイルを修正します。

```ruby:xxxxxxxxxxxx_create_tags.rb
class CreateTags < ActiveRecord::Migration[6.0]
  def change
    create_table :tags do |t|
      t.string :name, null: false

      t.timestamps
    end
  end
end
```

それでは、DBに反映させます。

```
$rails db:migrate
```

#モデルのアソシエーションの設定

```ruby:article_tag_relation.rb
class ArticleTagRelation < ApplicationRecord
  belongs_to :article
  belongs_to :tag
end
```

```article.rb
class Article < ApplicationRecord
  #Articlesテーブルから中間テーブルに対する関連付け
  has_many :article_tag_relations, dependent: :destroy
　#Articlesテーブルから中間テーブルを介してTagsテーブルへの関連付け
  has_many :tags, through: :article_tag_relations, dependent: :destroy
end
```

```tag.rb
class Tag < ApplicationRecord
　#Tagsテーブルから中間テーブルに対する関連付け
  has_many :article_tag_relations, dependent: :destroy
　#Tagsテーブルから中間テーブルを介してArticleテーブルへの関連付け
  has_many :articles, through: :article_tag_relations, dependent: :destroy
end
```

#タグのチェックボックスの作成

``` new.html.erb
<%= form_for @article do |f| %>
    <div class='form-group'>
        <%= f.collection_check_boxes(:tag_ids, Tag.all, :id, :name) do |tag| %>
            <div class='form-check'>
                <%= tag.label class: 'form-check-label' do %>
                    <%= tag.check_box class: 'form-check-input' %>
                    <%= tag.text %>
                <% end %>
            </div>
        <% end %>
    </div>

    <%= f.submit '保存', class: 'btn btn-primary' %>
<% end %>
```

入力フォームにタグの選択チェックボックスを表示するのに、` collection_check_boxes ` を使用します。
第一引数の`tag_ids`はタグIDのリストを渡し、複数のタグを掲示板に紐づけることができます。
第二引数には、タグオブジェクトのリスト。
第三引数にチェックボックスのvalue、第四引数にタグオブジェクトのnameプロパティをラベル名に指定。

- この状態では、まだTagsの中身は空なので、試しにテストデータを投入してみます。

```seeds.rb
Tag.create([
  { name: 'タグ1' },
  { name: 'タグ2' },
  { name: 'タグ3' },
  { name: 'タグ4' },
  { name: 'タグ5' }
])
```

```
$rails db:seed
```

<img width="1226" alt="スクリーンショット 2019-11-27 16.33.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451305/79bdee9b-e822-1b5c-6685-8cd46b6a507e.png">

先ほど投入したタグデータのチェックボックスが表示されていますね。


#コントローラーの作成

```articles_controller.rb
 class ArticlesController < ApplicationController

  def new
    @article = Article.new
  end

  def create
    article = Article.new(article_params)
    if article.save
      redirect_to article
    else
       redirect_to :back
    end
  end

  def show
    @article = Article.find(params[:id])
  end


  def destroy
    @article.destroy
    redirect_to articles_path
  end

  private

  def article_params
    params.require(:article).permit(:title, :body, tag_ids: [])
  end
end
```

今回はあくまでタグを表示するだけなので、かなり簡易的に実装します。

```
  def article_params
    params.require(:article).permit(:title, :body, tag_ids: [])
  end
```
ここで先ほどタグのチェックボックスで設定したtag_idsを許可します。
複数のtag_idが渡ってくるので配列の形式で記述しています。

#タグを表示する。
最後に、チェックしたタグを`show.html.erb`で表示してみたいと思います。

```show.html.erb
<% @article.tags.each do |tag| %>
    <span class= 'badge badge-primary'><%= tag.name %></span>
<% end %>
```

<img width="1226" alt="スクリーンショット 2019-11-27 16.34.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451305/ab4d2a06-4162-81b7-8d00-e781c0c64f20.png">

このように複数のタグをチェックした場合でも、表示できれば完成です。

#最後に
今回はタグをチェックボックスで選択し、記事に表示するまでの機能を実装してみました。
ユーザーが自由にタグを追加できたり、タグで絞り込みなどを行えるようにするなど個人アプリを作る場合には、更に幅を広げてみると面白いかもしれません。

以上。

#参考
- [フルスタックエンジニアが教える 即戦力Railsエンジニア養成講座](https://www.udemy.com/course/rails-kj/learn/lecture/9839504?start=300#overview)