Write Code or Die

RubyやRailsまたはバスケットボールや筋トレについて書きます。

ActiveAdminでカスタムフィルターを実装する

この記事は Fablic Developer’s Blog “inFablic” からの転載記事となります。元となる記事は2017年4月に公開されました。

こんにちは。サーバサイドエンジニアの @masacandy です。

最近MISTEL社のキーボードを購入したので快適にタイピングしながらお送りしております。

さて、今日はActiveAdminを利用する際に、カスタムフィルターを実装したい場合のお話をしたいと思います。

*ActiveAdminとは、管理画面を簡単に導入できるgemです。 github.com

テーブルに紐付いたカラムの内容で検索したい時

「特定のidのレコードを簡単に探したい」時や、「特定の期間に作られたレコードを探したい」時など、テーブルに紐付いているカラムの内容を条件にして検索したい場合は、ActiveAdminに搭載されている「フィルター」という機能を使います。

app/admin/items.rb

ActiveAdmin.register Item do
  filter :id
  filter :created_at
end

f:id:infablic:20170327153105p:plain

filter :検索したいカラム だけでこのように簡単なフィルター機能が実装できます。便利ですね。

カラムの型からよしなに検索方法も作ってくれたり、検索の方法もチェックボックスであったり日付で検索したりと柔軟にオプションが用意されています。

もっと気になる方は公式ドキュメントの方を参考にしてみてください。

複雑な条件で検索したい時

それでは本題に入ります。

上記のように紐付いたカラムで検索する際は簡単に実装することができるとわかりましたが、もう少し複雑な条件で検索したい時はどうすればよいでしょうか?

例えば、複数のカラムの条件から検索できるフィルターを作成したい場合 はどうすればよいでしょうか?

もっと具体的なシチュエーションで言えば、商品が「公開中かどうか」を deleted というカラムで管理しており、「販売済みかどうか」を souldout カラムで判断している場合に 販売中か削除済みか販売済みかの3つの選択肢で 検索をするフィルターを実装したい場合は一体どうしたら良いでしょうか?

カスタムフィルターの作成方法

実はActiveAdminの検索は内部でRansackというgemを利用しています。

そして、Ransackにはransackable_scopesという機能があり、この機能を使ってRansackの検索条件を拡張することができます。

これを利用するとActiveAdmin側でカスタムフィルターを実装することができます。

実装

まず、このransackable_scopesに探したい検索の方法をScopeとして追加します。

app/model/items.rb

class Item < ApplicationRecord
  # Ransackの自前Scopeには '0' や '1' が使えないので注意(参考: [http://qiita.com/t_oginogin/items/b45636d64c271ebc409c:title] )
  STATUS_OPEN = 2
  STATUS_DELETED = 3
  STATUS_SOLDOUT = 4

  scope :open, -> { where(deleted: false) }
  scope :deleted, -> { where(deleted: true) }
  scope :soldout, -> { where(soldout: true) }

  scope :complex_status, lambda { |status| 
    case status.to_i
    when STATUS_OPEN
      open
    when STATUS_DELETED
      deleted
    when STATUS_SOLDOUT
      soldout
    end
  }

  def self.ransackable_scopes(_auth_object = nil)
    %i(complex_status)
  end
end

そして、ActiveAdmin側で上記で追加したScopeをfilterとして利用します。

今回は特定の条件で探すケースなので、Select Boxを指定しました。

app/admin/items.rb

ActiveAdmin.register Item do
  filter :complex_status, label: '商品状態', as: :select, collection: proc { [(%w(販売中 2), %w(削除済み 3), %w(販売済み 4)] }
end

すると

f:id:infablic:20170327193732p:plain

より正確な商品状態の条件で検索できるフィルターを実装することができました。

まとめ

管理画面をお手軽に作れるActiveAdminのちょっとしたTipsでした。数行で複雑な条件検索が管理画面に実装できるのは嬉しいですね。

皆さんも是非参考にしてみてください。

参考