Railsでタグ投稿機能実装(導入編)

## gemを使ったタグ機能実装　(備忘録)
個人アプリ開発にて投稿した記事にタグを付けたいと思い実装しましたが、
gemの導入に手間が掛かったので備忘録として記事にしてみました！

<img width="1014" alt="スクリーンショット 2020-04-07 15.44.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526620/5975d5b2-85a3-e065-20e9-9ced4e6d423f.png">



## 開発環境
Rails バージョン5.2.4.1
ruby バージョン2.5.1
acts-as-taggable-on バージョン　6.0.0
データベース　mySQL

## タグ機能を実装するには

１．自分で実装する。
２．gem 'gutentag tags'を使用する
３．gem 'acts-as-taggable-on'を使用する

## 最初はgutentag tagsを使用して実装してみた
・タグ機能の実装について調べると「acts-as-taggable-on」は導入時にマイグレーションエラーが出るので、gutentag tagsで実装した記事を発見！内容も簡単そうだったので早速実装してみた。しかしエラーは出ないものの、DBに値が保存されない:disappointed_relieved:
（おそらく自身がルーティングをネストした場合のインスタンス変数の受け渡し等がマスターしてないのが原因です）

また、gutentag自体は、rails6にすぐ対応したcommitがある+issueのclose率も100%という点はあるが、patという創造者しかほぼ保守していないのとacts-as-taggable-onは、使ってる人が多いので、また修正版が上がるかもしれないという点を踏まえて「acts-as-taggable-on」で実装することにした。

↓gutentag tags参考記事
[gem”gutentag tags”を使ってタグ機能の実装~Ruby on Rails~](https://umakki.com/archives/264)
[Rails6でブログのタグのacts-as-taggable-onがエラーになったので別のタグgem(gutentag tags)を使う](https://qiita.com/jin-jar-ale/items/ee0e9e008ae8347eb44c)

## acts-as-taggable-onを使用して実装
'acts-as-taggable-on'はタグ機能を実装できるgem

色んなメソッドが用意されていますが、詳しくは参考記事またはGitHubを確認してみてください。

`find_related_skills`　　同じタグに関連するタスクが表示される
`taggings_count`　メソッドではないですが、該当のタグの使用回数が表示されている
`tag_counts`　全てのタグデータを取得できる

[Rails | acts-as-taggable-on を使ったタグ機能の実装 | 備忘録]
(https://qiita.com/ddgg7755/items/e1caa8b73d118822a0a2)
[acts-as-taggable-on Git Hub]
(https://github.com/mbleigh/acts-as-taggable-on)

## 導入内容

## 1.Gemを追加してインストール

```
(Gemfile)
gem 'acts-as-taggable-on', '~> 6.0' #追加
```

```
$ bundle install
```

## 2.マイグレーションファイルをインストール

```
$ rails acts_as_taggable_on_engine:install:migrations
```

成功するとマイグレーションファイルが追加される

```
Copied migration 20200406074226_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb from acts_as_taggable_on_engine
Copied migration 20200406074227_add_missing_unique_indices.acts_as_taggable_on_engine.rb from acts_as_taggable_on_engine
Copied migration 20200406074228_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb from acts_as_taggable_on_engine
Copied migration 20200406074229_add_missing_taggable_index.acts_as_taggable_on_engine.rb from acts_as_taggable_on_engine
Copied migration 20200406074230_change_collation_for_tag_names.acts_as_taggable_on_engine.rb from acts_as_taggable_on_engine
Copied migration 20200406074231_add_missing_indexes_on_taggings.acts_as_taggable_on_engine.rb from acts_as_taggable_on_engine
```

## 3.マイグレーションを実行

```
$ rails db:migrate
```

**しかし、ここでエラーが発生。**

```
Mysql2::Error: Cannot drop index 'index_taggings_on_tag_id': needed in a foreign key constraint: DROP INDEX `index_taggings_on_tag_id` ON `taggings`
~
ActiveRecord::StatementInvalid: Mysql2::Error: Cannot drop index 'index_taggings_on_tag_id': needed in a foreign key constraint: DROP INDEX `index_taggings_on_tag_id` ON `taggings`
~
Mysql2::Error: Cannot drop index 'index_taggings_on_tag_id': needed in a foreign key constraint
```
調べて見るとDBを**「mySQL」**にしている場合は初期導入で色々問題があるようなのでmigrateを実行する前に`rails acts_as_taggable_on_engine:tag_names:collate_bin`を実行する必要があります。
※tagsテーブルのnameカラムは'binary encoded string'(パソコンで扱う2真数の文字列)として読み込まれるので、'utf8_bin'で読まなければいけないらしいです。

```
$ rails acts_as_taggable_on_engine:tag_names:collate_bin #実行
```

また、**gemのバグ**で、
`acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb`の
の15行目で外部キーを設定しているにも関わらず、

```ruby
t.references :tag, foreign_key: { to_table: ActsAsTaggableOn.tags_table }
```
`add_missing_unique_indices.acts_as_taggable_on_engine.rb`の11行目で外部キーを削除せずにインデックスを削除しようとしているためエラーが出ます。

```ruby
remove_index ActsAsTaggableOn.taggings_table, :tag_id if index_exists?(ActsAsTaggableOn.taggings_table, :tag_id)
```

GitHubのissuesから不具合報告の内容を確認

```ruby
(add_missing_unique_indices.acts_as_taggable_on_engine.rb)
remove_index ActsAsTaggableOn.taggings_table, :tag_id if index_exists?(ActsAsTaggableOn.taggings_table, :tag_id) #削除
if index_exists?(ActsAsTaggableOn.taggings_table, :tag_id) #追加
  remove_foreign_key :taggings, :tags                      #追加
  remove_index ActsAsTaggableOn.taggings_table, :tag_id    #追加
end                                                        #追加
```

[Fix: マイグレーションがエラーになる不具合を修正]
(https://github.com/daikideal/joblink/commit/7b0eb095b1e2dcf0562fbbfc43bb88773434a84d)

これでマイグレーションファイルが導入できます！
バグ解消前に`rails db:migrate`を実行した場合は、ArgumentErrorが出ます。
一度目のmigrate実行時に最初のファイルだけ読み込んでるからですね！
その場合は`rails db: rollback`でmigrateを実行する前の状態に戻しましょう。

*`rails db:migrate:status`で６つのファイルが「down」状態になってることを確認しましょう。
<img width="624" alt="スクリーンショット 2020-04-07 13.37.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526620/6f0068f7-e1ea-2d8f-834a-62e7fff93c97.png">


## 最後に
少し長くなってしまったので、実装内容は別の記事で投稿しようと思ってます。

他に参考にした記事は以下のとおりです。
[acts-as-taggable-on導入時のエラー]
(https://teratail.com/questions/224720)
[Rails 5.2でタグ投稿機能の実装のためgem「acts-as-taggable-on」を使ってみた]
(https://hirocorpblog.com/rails-5-2%E3%81%A7gem%E3%80%8Cacts-as-taggable-on%E3%80%8D%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%9F/)

実装編投稿しました！
合わせて参考にしていただければと思います。
[Railsでタグ投稿機能実装(実装編)](https://qiita.com/kazuhj/items/31d3b1751d9c957b789f)