Oasistブログ

言語学、エンジニアリング、ライフ記事を気まぐれにお届け

Ransack検索フォーム

f:id:oasist:20200614004721p:plain
Ruby on Rails

Contents

1. 環境

2. 要件

Users can search for events with

  • name: 含む
  • place: 含む
  • content: 含む
  • start_at: 以降
  • end_at: 以前

3. Gemfile

ransackGemfileに追加し、docker-compose exec app bin/rails bundle を実行する。

source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.7.2'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 6.0.3', '>= 6.0.3.2'
...

# SearchForm
gem 'ransack', '~> 2.3.2'

4. コントローラー

コントローラーにて、ビューから送信される params[:q] 値を ransack クラスメソッドの引数に指定し、結果を result インスタンスメソッドで呼び出し=、表示するイベントを @events インスタンス変数に代入する。

def index
  @q = Event.ransack(params[:q])
  @events = @q.result.page(params[:page]).per(paginate_per).default
end

5. ビュー

Ransackは以下のビューで利用可能な {attr}_{options} ヘルパーメソッドを提供している。

オプション 意味 記号
*_eq 等しい ==
*_noteq 等しくない !=
*_lt 未満 <
*_lteq 以下 <=
*_gt より上 >
*_gteq 以上 >=
*_cont 含む

各属性に適切なオプションを適用し、form_with ヘルパーメソッドで検索フォームを実装する。

<div class="panel panel-default panel-search">
  <div class="panel-body">
    <%= search_form_for(@q, class: 'mb-5') do |f| %>
      <div class="row form-group">
        <div class="col-sm-6">
          <%= f.label :name_cont, Event.human_attribute_name(:name), class: 'control-label col-sm-5 nowrap' %>
          <div class="col-sm-11 col-md-9">
            <%= f.search_field :name_cont, class: 'form-control' %>
          </div>
        </div>
        <div class="col-sm-6">
          <%= f.label :place_cont, Event.human_attribute_name(:place), class: 'control-label col-sm-5 nowrap' %>
          <div class="col-sm-11 col-md-9">
            <%= f.search_field :place_cont, class: 'form-control' %>
          </div>
        </div>
      </div>
      <div class="row form-group">
        <div class="col-sm-12">
          <%= f.label :content_cont, Event.human_attribute_name(:content), class: 'control-label col-sm-5 nowrap' %>
          <div class="col-sm-11 col-md-10">
            <%= f.search_field :content_cont, class: 'form-control' %>
          </div>
        </div>
      </div>
      <div class="row form-group">
        <div class="col-sm-6">
          <%= f.label :start_at_gteq, Event.human_attribute_name(:start_at), class: 'control-label col-sm-5 nowrap' %>
          <div class="col-sm-11 col-md-9">
            <%= f.datetime_field :start_at_gteq, class: 'form-control' %>
          </div>
        </div>
        <div class="col-sm-6">
          <%= f.label :end_at_lteq, Event.human_attribute_name(:end_at), class: 'control-label col-sm-5 nowrap' %>
          <div class="col-sm-11 col-md-9">
            <%= f.datetime_field :end_at_lteq, class: 'form-control' %>
          </div>
        </div>
      </div>
      <div class="form-btn-field">
        <%= f.submit class: 'btn btn-primary' %>
      </div>
    <% end %>
  </div>
</div>

6. アセット

ページネーションのヘッダーとフッターに適用するスタイルを /app/assets/stylesheets/ransack.scss に定義する。

.panel {
  margin-top: 20px;
  margin-bottom: 20px;
  background-color: #fff;
  border: 1px solid transparent;
  border-radius: 4px;
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
  &-default {
    border-color: #ddd;
  }
  &-body {
    padding: 15px;
  }
}

.form-btn-field {
  margin-top: 20px;
  text-align: center;
}

7. 成果物

f:id:oasist:20201123125400p:plain
Ransack Search Form