Ruby on Railsの学習として検索機能を作ってみました。
色々と調べて覚えたことをまとめておきます。
検索画面のURL
条件を指定してデータを検索する画面のURLとアクションをどうしようか考えた記録。
検索フォームでもform_forが使える
データベースのテーブルと項目が完全に一致しないフォームであっても、ActiveModelを定義することでform_for
に渡すことができます。
検索条件フォームのようにテーブルと完全に同一でないフォームもform_forを使って実装できる
選択項目を生成してくれるヘルパーがある
ラジオボタンやチェックボックスのHTMLを自動生成してくれるヘルパーメソッド
- collection_select
- collection_radio_buttons
- collection_check_boxes
<%= form_for @form, url: '/employees', method: :get do |f| %>
<%= f.collection_select :department_id, Department.all, :id, :name %>
<%= f.collection_radio_buttons :sex_id, Sex.all, :id, :name %>
<%= f.collection_check_boxes :favorite_ids, Favorite.all, :id, :name, checked: @form.favorite_ids %>
<% end %>
collection_check_boxes
はchecked:
オプションで値の配列を渡さないと初期表示のチェックが付いてくれませんでした。
選択項目の「指定しない」という項目
ラジオボタンは一度チェックすると、未チェックの状態に戻すことができません。なので、「指定しない」という項目を追加しました。
プルダウンの項目は、collection_select
のオプションでinclude_blank: true
を指定することで空の項目が追加されます。
検索条件を組み立てる処理はmodelに書く
データベースから指定された条件に該当するデータを取得するために、モデルのwhere
メソッドに渡す条件を組み立てる処理をコントローラに書くと、if文の連続でグチャグチャしたものが出来上がります。
モデルのscope
メソッドで、ひとつひとつの検索条件に対するクラスメソッドを定義することができます。scope
で定義されたクラスメソッドは、デフォルトでall
を返すので、条件が指定された時だけwhereするということがシンプルに実装できます。
# nameが空でない場合は氏名を部分一致検索する条件を返す
# nameが空文字の場合はallが返る
scope :name_like, -> name { where('name like ?', "%#{name}%") if name.present? }