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? }
