フタミノブログ

マーケティングから技術まで色々

【Rails5】Acts-as-taggable-onとRansackを一緒に使用する

f:id:nimi0370376:20170924013942p:plain

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以外の実装方法も少し考えておきましょう。 頼りすぎるといざという時にハマります…