この記事について
タグ付け機能を実装したRailsのアプリケーションにタグ名の検索機能を実装しようとしたところ、つまずいた部分があったのでその解決策をまとめました。
環境
Rails6 (6.0.1)
ruby 2.7.0
参考
Rails6でブログのタグのacts-as-taggable-onがエラーになったので別のタグgem(gutentag tags)を使う
Ransack on Gutentag tags- undefined method `type' for nil:NilClass
https://github.com/pat/gutentag
https://qiita.com/ishidamakot/items/d50ed387fbd2e80f702d
Ransackとは
Railsで作成したアプリケーションに検索機能を実装するためのgemです。 Ransackを利用することで複数の条件を組み合わせた複雑な検索機能を簡単に実装することができます。
Gutentagとは
Railsで作成したアプリケーションにタグ付け機能を実装するためのgemです。 Railsでタグ付け機能を実装する場合はacts-as-taggable-onというgemを使うので一般的ですが、こちらの記事にあるようにRails6では不具合が発生している模様で、今回はこちらのgemを利用しました。
つまずいたところ
私自身はRails5でacts-as-taggable-onとransackを組み合わせて検索機能を実装した経験があったので、同じようにでGutentagとRansackで検索機能を実装しようとしました。
具体的には、DBに保存されている記事のタイトル、記事の本文、記事のタグ名をOR検索するという処理内容。コードは以下。
Model
def self.make_search_query(search_word)
query = {}
query[:combinator] = 'or'
query[:groupings] = []
search_word = '' if search_word.nil?
search_word.split(/[ ]/).each_with_index do |word, i|
query[:groupings][i] = { title_or_content_or_tags_name_cont_any: word }
end
Article.ransack(query)
end
Controller
def search
Article.make_search_query(@search_word).result(distinct: true)
end
これで検索処理を走らせたら
以下のエラーが発生してしまった。
NoMethodError: undefined method `type' for nil:NilClass
どうやらタグ名検索のところでエラーが発生している模様。
解決した方法
こちらのサイトに同じような問題に直面した人が質問しており、解決策も提示されていました。
どうやらGutentagをインストールすることで作成されるgutentag_tagsテーブルはransackの検索対象に含まれていないらしいです。そのため、検索対象に含めるようにconfig/initializersに設定ファイルを置かなければならないとのこと。
設定ファイルの内容は以下
if ActiveRecord::Base.connection.table_exists? 'gutentag_tags'
model = Object.const_get "Gutentag::Tag"
model.singleton_class.class_eval do
define_method(:ransackable_attributes) do |auth_object|
auth_object = nil
['name']
end
end
end
このコードを自分なりに解釈すると
1.gutentag_tagsテーブルが存在するか確認する
2.存在する場合はObject.const_getで"Gutentag::Tag"クラスを取得する
3.singleton_class.class_evalによって特異クラスを定義する
4.ransackable_attributesメソッドを定義し、nameカラムを検索対象に指定。
という感じ。
これで、gutentag_tagsテーブルのnameカラムがRansackの検索対象になるようです。
とりあえず、再度Railsを再起動して検索処理を走らせると、無事にタグ名での検索も実行されました。
※ransackではransackable_attributesメソッドで検索対象とするカラムを指定することができます。
参考:https://qiita.com/ishidamakot/items/d50ed387fbd2e80f702d#検索できる項目の制限
まとめ
RansackとGutentagを使ってタグの検索機能を実装した際に、タグ名で検索されないというエラーが発生しましたが、gutentag_tagsテーブルのnameカラムをRansackの検索対象に指定することで解決することができました。gutentagに関する情報は少ないので、少しでもお役に立てれば幸いです。ただ、個人的にはObject.const_getやsingleton_class.class_evalなど100%は理解できていないので、もっと勉強が必要。