162
184

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Rails | acts-as-taggable-on を使ったタグ機能の実装 | 備忘録

Last updated at Posted at 2019-02-21

gemを使ったタグ機能実装 備忘録

タグ機能をgemを使って実装してみました。
毎回自分自身調べて実装しているので、いい加減備忘録として記事にしてみました。

前半の内容は、すでに多くの人が記事にしている基本的なタグ機能の実装内容です。
後半は、タグによる絞り込み検索をやってみました。初心者の自分にとっては、結構苦戦しましたが、理解すれば意外とシンプルな構造になっています。

ちなみに下記のリンクを参考にして実装しています。
<参考リンク>
公式リファレンス:acts-as-taggable-on
Railsでacts-as-taggable-onを使ってタグ管理を行う - Rails Webook

開発環境

Rails バージョン5.2.2
ruby バージョン2.5.3
acts-as-taggable-on バージョン 6.0.0  → 今回使用したタグ機能のgem
bootstrap4

アプリケーション詳細

ベースは現場Railsのタスク管理アプリを使用しています。

acts-as-taggable-on について

  • タグ機能を実装できるgem
    以前gemを使用せずにタグ機能を実装した時は、中間テーブルを作ったりと色々やりましたが、このgemを使うと一瞬でできます。

  • 当たり前ですが、色んなメソッドが用意されている

find_related_skills  同じタグに関連するタスクが表示される
taggings_count メソッドではないですが、該当のタグの使用回数が表示されている
tag_counts 全てのタグデータを取得できる
などなど.....他にもまだありました。

使い方等はリファレンスを参照してください。

  • 同じ名前で登録したタグの場合は、同じIDになるようになっている

例:Railsと別々のタスクで登録しても同じidになる

実装内容

1. Gemfileに追加して、インストール

gemfile
gem 'acts-as-taggable-on', '~> 6.0' #追加
$ bundle install
$ rails acts_as_taggable_on_engine:install:migrations
$ rails db:migrate

2. モデルとコントローラーに追加

対象のモデルとコントローラーに下記を追加する

task.rb
class Task < ActiveRecord::Base
  acts_as_taggable #追加
  # acts_as_taggable_on :tags と同じ意味のエイリアス
  # tags のなかにIDやら名前などが入る。イメージ的には親情報。

	#略
	
end
tasks_controller.rb
class TasksController < ApplicationController

	#略
	
  private

  def task_params
    params.require(:user).permit(:name, :description, :tag_list) 
    #tag_list を追加
  end
	
	#略
	
end

3. 各ビューファイルの編集

まず、各Viewファイルを下記のように編集していく。

① タスク登録フォームにてタグを入力できるようにする

_form.html.slim
= form_with model: task, local:true do |f|
  .form-group
    = f.label :name 
    = f.text_field :name, class: 'form-control', id: 'task_name'
  .form-group
    = f.label :description 
    = f.text_area :description, rows: 5, class: 'form-control', id: 'task_description'
    #タグ入力フォームを追加
  .form-group 
    = f.label :tag_list
    = f.text_field :tag_list, value: @task.tag_list.join(','), class: "form-control"
  
  .form-group
    = f.label :image 
    = f.file_field :image, class: 'form-control'
  = f.submit nil, class: 'btn btn-primary'

② 入力されたタグが配列としてtag_listに代入されていく。

スクリーンショット 2019-02-21 15.35.11.png

@task.tag_list.join(',')のおかけで,で区切って複数のタグを入力できる

ここで、
rails, php, js, python
と入力した場合は、
tag_list = ["rails","php","js","python"]
という配列になる。

③ タスク一覧画面にタグを表示させる

index.html.slim
 - @tasks.each do |task|
     tr id="task-#{task.id}"
        td= link_to task.name, task_path(task)
        td= task.created_at
	    #タグ表示欄を追加
        td= render 'tasks/tag_list', tag_list: task.tag_list
        
	    td
          = link_to '編集', edit_task_path(task), class: 'btn btn-primary mr-3'
          = link_to '削除', task, method: :delete, remote: true, data: {confirm: "タスク「#{task.name}」を削除します。よろしいですか?"}, class: 'btn btn-danger delete', id: "delete_link_#{task.id}"

タスク詳細画面でも同じ表示の仕方をするのでrenderを利用してパーシャルファイルで処理してもらう。
パーシャルに流す前の処理としては、
taskには@tasksから取り出した一つのタスクデータが入っている。
tag_listをメソッドとして使用すると、タスクに付いているタグが取り出せる。
tag_listtask.tag_listで取り出したタグをパラメータとして渡してあげる。

④ 受け取ったパラメータを繰り返し処理し、一つ一つを分けて表示させる

_tag_list.html.slim
- tag_list.each do |tag|
  span.badge.badge-primary.mr-1.p-2= tag

この時、tag_listに入っているタグをeachで一つ一つ独立させている

スクリーンショット 2019-02-21 15.37.28.png

ここまで実装すると、上記の画像のようにタグが表示されます。
もちろん編集も可能です。

ここまでが基本的なタグ機能の実装です。

4. タグの絞り込み機能の追加

タグをクリックすると同じタグが付いたタスクを絞り込めるように実装していきます。

gemを使わずにタグ機能を実装した時は、この絞り込み機能がめちゃくちゃ苦戦しました。
ただ、gemを使う場合は、逆に完成されているために何をどう変えたらいいのか、どう使ったらいいのかわからなかったので苦戦しましたが、、、

実装内容は以下の通りです。
やっていることは結構シンプルです。

先ほど実装したものを少しだけいじります。

① タグにリンクをつける

link_toメソッドを使用してリンクにします。
このブロック内のtagには一つだけのタグ名が入っている状況です。

_tag_list.html.slim
- tag_list.each do |tag|
  span.badge.badge-primary.mr-1.p-2
    = link_to tag, tasks_path(tag_name: tag), class: "text-white"

② リンク先にパラメータを渡す

このtagのタグ名をクリックした時の遷移先をタスク一覧画面にする。
その際、tag_nametagのタグ名をパラメータとして渡してあげる。

例: ここでtagRailsというタグが入っていた場合は、Railsというタグ名が一覧画面へパラメータとして渡される。

③ コントローラーで処理する

tasks_controller.rb
def index
    #略
    #タグ絞り込み
    if params[:tag_name]
      @tasks = Task.tagged_with("#{params[:tag_name]}")
    end
end

tasksコントローラーのindexアクションにて処理します。

ここで便利なメソッドが登場。
tagged_with("タグ名")で絞り込みができます。
(もちろん公式リファレンスにも載っています。)

なので、もしtag_nameに値が入っている場合は(タグをクリックされたら)
受け取ったtag_nametagged_with("タグ名")タグ名に入れて絞り込みを実行してくれます。
処理が実行されると、同じtag_nameを持ったタスクが一覧で表示される仕組みです。

URLもhttp://localhost:3000/tasks?tag_name=Railsとクリックしたタグ名で絞り込みができていることがわかります。

: もしRailsというタグをクリックしたら
tag_nameRailsという値を持って、indexアクションに渡されます。
そして、tagged_with("Rails")という形になり、絞り込みが実行される

さいごに

gemは非常に便利ですが、少し変えようと思ったときに、何をしていいかわからなくなるのが現状でした。
ですが、リファレンスをしっかり読み、構造を少しでも理解すれば意外と頑張れるとうこともわかりました。
これからはリファレンスファーストを意識して取り組んでいければと思います。

読んでいただき、ありがとうございました。

備忘録として記事を書きましたが、もし間違っている内容等あればお気軽に編集リクエストをしていただければと思います。

以上です。

162
184
11

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
162
184

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?