[Ruby on Rails 5] form_with でシンプルなサーチフォームを作成する

RailsCasts の Simple Search Form を復習。
form_with で書き換えます。

復習

テキストフィールドに検索ワードを入力するシンプルなフォーム。

View

/items?utf8=✓&search=foo とするためには method: :getname: nil がポイントです。
以下で付与されている class は Bootstrap のものです。

app/views/items/index.html.haml
= form_tag items_path, method: :get do
  .form-group
    = label_tag :search
    = text_field_tag :search, '', class: 'form-control'
  .form-group
    = label_tag :price
    = number_field_tag :min_price, '', class: 'form-control', placeholder: 'min. price'
    = number_field_tag :max_price, '', class: 'form-control', placeholder: 'max. price'
  = submit_tag 'Search', class: 'btn btn-primary', name: nil

Controller

コントローラでは、models/item#search クラスメソッドを呼ぶだけにします。
ページネーションがあれば .page(params[:page]) を追加します。

app/controllers/items_controller.rb
class ItemsController < ApplicationController
  before_action :set_item, only: [:show, :edit, :update, :destroy]
  def index
    @items = Item.search(params).page(params[:page])
  end

Model

プレースホルダ name LIKE ? を利用して where で絞り込みます。
いくつか検索条件も追加します。

app/models/item.rb
class Item < ApplicationRecord
  def self.search(params)
    results = all.order(created_at: :desc)
    results = results.where('name LIKE ?', "%#{params[:search]}%") if params[:search].present?
    results = results.where('price >= ?', params[:min_price]) if params[:min_price].present?
    results = results.where('price <= ?', params[:max_price]) if params[:max_price].present?
    results
  end

form_with

Rails v5.1 で form_with が導入されました。

書き直してみます。

app/views/items/index.html.haml
= form_with url: items_path, method: :get, local: true do |f|
  .form-group
    = f.label :search
    = f.text_field :search, class: 'form-control'
  .form-group
    = f.label :price
    = f.number_field :min_price, class: 'form-control', placeholder: 'min. price'
    = f.number_field :max_price, class: 'form-control', placeholder: 'max. price'
  = f.submit 'Search', class: 'btn btn-primary', name: nil

補遺