この記事では、Ruby on RailsでRansackを使ってモデルの検索を行う際に発生したエラーの解決方法について説明します。特に、関連するモデルの属性に対する検索のためのホワイトリストの設定や、カスタム検索の実装について触れます。
背景
Railsアプリケーションで、Reservation
モデルの検索を行い、予約をした顧客単位で検索する必要がありました。しかし、Ransackの設定や関連するモデルへのアクセスに問題が発生し、検索フォームが正しく動作しないという課題が生じました。
エラー内容
Reservation検索を実装するために、ビューで以下のようにフォームを設定していました:
<%= search_form_for @r, url: reservations_path, method: :get, local: true, class: 'custom-form-group d-flex' do |form| %>
<div class="form-group d-flex align-items-end me-2">
<div class="w-100">
<label>顧客名検索:</label>
<%= form.search_field :customer_name_cont, id: 'single-simple-search-name_cont', class: 'form-control me-2', placeholder: '顧客名検索' %>
</div>
</div>
<%= form.submit '検索', class: 'btn btn-primary' %>
<% end %>
しかし、これに対して以下のエラーが発生しました:
RuntimeError at /reservations
Ransack needs Customer attributes explicitly allowlisted as searchable.
このエラーは、Ransackが関連するCustomer
モデルの属性にアクセスできないために発生しています。
解決方法
-
Customer
モデルでのransackable_attributes
メソッドの追加:この問題を解決するため、
Customer
モデルに対するホワイトリストメソッドを追加します:class Customer < ApplicationRecord # その他のモデル設定... def self.ransackable_attributes(auth_object = nil) %w[city created_at description email id name postal_code prefecture street_address telephone updated_at] end end
このメソッドで、
Customer
モデルの検索に必要な属性をホワイトリスト化し、Ransackが正常に検索できるようにします。 -
Reservation
モデルのカスタムransackerの追加:次に、
Reservation
モデルで顧客単位での検索を行うためのカスタムransackerを追加します:class Reservation < ApplicationRecord # その他の設定... ransacker :customer_name do |parent| # Reservationのcustomer_idを元に、関連するCustomer.nameで検索するための設定 Arel::Nodes::InfixOperation.new('LIKE', parent.table[:customer_id], '%') end def self.ransackable_attributes(auth_object = nil) %w[company_id created_at customer_id date ...] end end
-
ビューでの検索フォーム:
最後に、ビュー内で以下のように検索フォームを設定し、
customer_name_cont
などのフィールドで検索ができるようにします:<%= search_form_for @r, url: reservations_path, method: :get, local: true, class: 'custom-form-group d-flex' do |form| %> <div class="form-group d-flex align-items-end me-2"> <div class="w-100"> <label>顧客名検索:</label> <%= form.search_field :customer_name_cont, id: 'single-simple-search-name_cont', class: 'form-control me-2', placeholder: '顧客名検索' %> </div> <% end %>
これらの修正により、RansackでReservation
モデルの検索を顧客単位で行うことができるようになります。
次回の記事