【Rails5】Acts-as-taggable-onとRansackを一緒に使用する
Railsでタグ機能の実装とスコープ機能を利用した時にハマったのでここにメモ残しておきます。
やりたいこと
上記の2点をやりたいと思っていました。
また、Ransackを利用した検索機能も利用していました。後述しますがこのRansackでハマりました…
Acts-as-taggable-onを利用したタグ機能実装
Gemfile
gem 'acts-as-taggable-on'
routes.rb
get 'tags/:tag', to: 'articles#index', as: :tag
articles_controller.rb
def index if params[:tag] @articles = Article.tagged_with(params[:tag]) else @articles = Article.all end @articles = @search_articles.order(created_at: :desc).page(params[:page]) end
index.html+pc.erb
<% @search_articles.each_with_index do|article,i|%> # 省略 <div class="tag"> <span> <%= raw(article.tag_list.map { |t| link_to t, tag_path(t) }.join(' / ')) %> </span> </div> <%end%> <div class="paginate"> <%= paginate @articles%> </div> # 以下略
以上のようになっていました。 実際これでデータベースを作って、formを整えればタグ機能は実装できます。
記事の絞り込みができない
実は上記の実装だと記事の絞り込みができません。 タグをクリックしても記事一覧のままです。
主な原因は下記
- indexアクションで@articlesを呼び出しているのに、indexでは@search_articlesを呼び出してる
なぜこんな簡単なことに気がつかなかったのか… つまりビューとコントローラーを下記のように書き換えればOK
articles_controller.rb
def index if params[:tag] @search_articles = Article.tagged_with(params[:tag]) else @search_articles = Article.all end @search_articles = @search_articles.order(created_at: :desc).page(params[:page]) end
index.html+pc.erb
# 省略 <div class="paginate"> <%= paginate @search_articles%> </div>
最初から@search_articlesにそれぞれ入れてあげます。 ビューファイルでは@search_articlesを呼び出してあげればいいです。
@search_articlesを使う理由
そもそも最初から教科書通り@articlesにオブジェクトを格納していけばこんな不具合は起こりません。 @search_articlesを使用する理由は、ransackというgemを利用しているからです。
ransackはRailsで検索機能を実装する際に使うGemです。ransackを実装する際に@search_articlesにしていたのです。 全部Gemから実装しようとする場合には気をつけましょう。
今回の学び
今回の不都合は、
- 全部Gemで実装を済ませようとしたこと
- コントローラーの実装を適当にしてた
の2点から起こったと言えます。
railsのgemは非常に便利ですが、頼る際にはある程度gem以外の実装方法も少し考えておきましょう。
頼りすぎるといざという時にハマります…