【Ruby on rails6】acts-as-taggable-onを使ってタグ付け機能実装

【Ruby on rails6】acts-as-taggable-onを使ってタグ付け機能実装

今回はRails6でacts-as-taggable-onを使用してタグ管理機能を作成する方法をやっていきたいと思います。

acts-as-taggable-onのgithub↓

A tagging plugin for Rails applications that allows for custom tagging along dyn…
github.com

1.Gemfileに必要内容を記入し、インストール

gem 'acts-as-taggable-on', '~> 9.0'

この記述をしたらいつも通りbundle install。これでgemの導入は完了しました。

2.専用のmigrationファイルの作成

rails acts_as_taggable_on_engine:install:migrations

こちらのコマンドを入力すると、7つのmigrationファイルが作成される。しっかりとmigrationファイルが作成されているのを確認したらいつも通りmigrateをする。これでタグを格納する用のモデルの作成が完了しました。この流れを見るとなんかActiveStorageの時と似ていますね。

3.タグを付与するための記述をモデルファイルに書く

今回はbookモデルという場所に書いていきます。

class Book < ApplicationRecord
  #ここを追記
  acts_as_taggable_on :tags
  belongs_to :user
  has_many :favorites, dependent: :destroy
  has_many :book_comments, dependent: :destroy

  validates :title,presence:true
  validates :body,presence:true,length:{maximum:200}

  def favorited_by?(user)
    favorites.exists?(user_id: user.id)
  end

  def self.looks(search, word)
    if search == "perfect_match"
      @book = Book.where("title LIKE?","#{word}")
    elsif search == "forward_match"
      @book = Book.where("title LIKE?","#{word}%")
    elsif search == "backward_match"
      @book = Book.where("title LIKE?","%#{word}")
    elsif search == "partial_match"
      @book = Book.where("title LIKE?","%#{word}%")
    else
      @book = Book.all
    end
  end
end

追記した:tagsという場所にidやタグ名が入るようになっている。

4.コントローラに追記

今度はbooksコントローラにタグを追加するための記述を追記していく。

class BooksController < ApplicationController
  (略)
  private

  def book_params
    params.require(:book).permit(:title, :body, :tag_list)
    # tag_listを追記
  end
end

これを記述することにより、入力された内容がtag_listに配列として格納されるようになる。

5.フォームのビューを編集

タグを作成する準備は完了したので、次はそのタグを作成するために今あるフォームにタグを記述する場所を追記していきます。

<%= form_with model:book,local:true do |f| %>
  <div id="error_explanation">
    <% if book.errors.any? %>
      <h3><%= book.errors.count %>errors prohibited this obj from being saved:</h3>
      <ul>
        <% book.errors.full_messages.each do |message| %>
          <li><%= message %></li>
        <% end %>
      </ul>
    <% end %>
  </div>
  <div class="form-group">
    <%= f.label :title %>
    <%= f.text_field :title, class: 'form-control book_title' %>
  </div>
  <div class="form-group">
    <%= f.label :opinion %>
    <%= f.text_area :body, class: 'form-control book_body' %>
  </div>
  <div class="form-group">
    <%= f.label :tag_list %>
    <%= f.text_field :tag_list, value: book.tag_list.join(','), class: 'form-control' %>
  </div>
  <div class="form-group">
    <%= f.submit class: 'btn btn-success' %>
  </div>
<% end %>

このように記述する。:tag_listのformにあるvalueではタグを”,”で区切ると複数タグづけでき、複数タグを保存することができるようになっている。

6.一覧でタグを見れるようにする

まずはタグを表示させるための部分テンプレートを作成する。

<% tag_list.each do |tag|%>
  <div class="btn btn-primary">
    <%= tag %>
  </div>
<% end %>

部分テンプレートを作成したら、一覧ページでその部分テンプレートを呼び出す。

<table class='table table-hover table-inverse'>
  <thead>
    <tr>
      <th></th>
      <th>Title</th>
      <th>Opinion</th>
      <th>Tag</th>
      <th colspan="4"></th>
    </tr>
  </thead>
  <tbody>
    <% books.each do |book| %>
      <tr>
        <td><%= link_to(book.user) do %>
          <%= image_tag book.user.get_profile_image, size:'50x50' %>
          <% end %>
        </td>
        <td><%= link_to book.title,book %></td>
        <td><%= book.body %></td>
        <td><%= render 'books/tag_list', tag_list: book.tag_list %></td>
        <td id="favorite_buttons_<%= book.id %>">
          <%= render "favorites/favorite", book: book %>
        </td>
        <td><%= "コメント数: #{book.book_comments.count}" %></td>
      </tr>
    <% end %>
  </tbody>
</table>
<%= paginate books %>

tag_listの変数にはbookについているタグを入れればいいので、book.tag_listのようにする。

このようにフォームを入力したものが、

このように一覧表示させることができるようになる。

7.タグでの絞り込み機能を作る

タグを付ける機能は作成できたが、タグをつけれるということはそのタグにどのような投稿があるのか絞り込めるようになっているととても便利になってきます。なので、そちらをやっていきます。

まずは、先ほどのタグにlinkをつけていきます。

<% tag_list.each do |tag|%>
  <div class="btn btn-primary">
    <%= link_to tag, books_path(tag_name: tag), class: "text-white" %>
  </div>
<% end %>

今回はbooksのindexページでタグの検索結果を表示させるので、books_pathを指定します。
あとはコントローラでタグをクリックした際の処理を書いてあげます。

def index
  @books = Book.all.page(params[:page]).per(5)
  @book = Book.new
  if params[:tag_name]
    @books = Book.tagged_with("#{params[:tag_name]}").page(params[:page]).per(5)
  end
end

このように記述すれば完成です。

このように”rails”というtagをクリックすると、urlにtag_name=railsが渡され、”rails”というタグがついているものだけが表示されるようになりました。

おわり

今回はacts-as-taggable-onを使ったタグ付け機能についてやってみました。このgemを使う時にマイグレーションファイルが一気にいっぱい作られたため、ちょっと戸惑いましたが、無事に実装することができました。他にもいろいろできるようですのでリファレンスを読んでおきたいと思います。最後まで読んでくださりありがとうございました!それではまた別の記事でお会いしましょう!

カテゴリー

naska