Railsアプリケーションにおいて、テーブルA(hospitals)
とテーブルB(business_days)
間の関係を管理するためにテーブルAB(hospital_business_days)
中間テーブルを設定し、さらにそれにテーブルC(hospital_business_hours)
を1対多で関連付ける場合、複雑なフォームの扱いが必要になることがあります。本記事では、このような構成をaccepts_nested_attributes_for
を用いて実装し、チェックボックスで選択された曜日に応じて営業時間の入力フォームを動的に表示する方法を解説します。
📌 重要な参考資料 📌
▶️ 以下の記事も参考にしてください。 ◀️
Railsアプリケーションにおける外部キー制約エラーの解決法
実装の概要
実装の核となるのは、次の4つの部分です。
※実際に私が使用した記述を引用しているのでテーブル名等は各自必要なものに読み替えてください。
-
モデルの関連付け:
hospital
とbusiness_day
の間に中間テーブルhospital_business_day
を設定し、hospital_business_day
からhospital_business_hour
への1対多の関連付けを行います。 -
ビューの構築:
フォームでは、開院日を選択するチェックボックスと、選択された曜日に応じて表示される営業時間入力フィールドを含めます。 -
JavaScriptによる動的なフォームの更新:
チェックボックスの選択状態に基づいて、非同期通信で営業時間の入力フィールドを動的に更新します。 -
ストロングパラメータの設定:
フォームから送信されるパラメータを適切に扱うため、ストロングパラメータを正確に設定する必要があります。
ビューの実装
以下は、hospital
の編集フォームと、動的に更新される営業時間入力フィールドのビューの例です。
<h2><%= resource_name.to_s.humanize %>の編集</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }, remote: true ) do |f| %>
<%= render "hospitals/shared/error_messages", resource: resource %>
<%= render 'common_fields', f: f, selected_days: @selected_days %>
<div class="actions">
<%= f.submit "更新" %>
</div>
<% end %>
<div class="hospital-field">
<%= f.label :開院日, class: 'column-label' %><br />
<%= f.collection_check_boxes(:business_day_ids, BusinessDay.all, :id, :day_of_week) %>
</div>
<div class="hospital-field">
<%= f.label :開院時間, class: 'column-label' %><br />
<table>
<thead>
<tr>
<th>曜日</th>
<th>開始時間</th>
<th>終業時間</th>
</tr>
</thead>
<tbody id="business-hours-table">
<!-- 動的に更新される部分 -->
</tbody>
</table>
</div>
JavaScriptによる動的な更新
チェックボックスの状態変化を
検知し、非同期通信で営業時間入力フィールドを更新するJavaScriptの実装例です。
$(document).on('turbolinks:load', function() {
$('input[name="hospital\\[business_day_ids\\]\\[\\]"][type="checkbox"]').change(function() {
var selectedDays = $('input[name="hospital\\[business_day_ids\\]\\[\\]"][type="checkbox"]:checked').map(function() {
return $(this).val();
}).get();
$.ajax({
url: '/hospitals/update_business_hours',
method: 'POST',
data: { selected_days: selectedDays },
success: function(data) {
$('#business-hours-table').html(data);
}
});
});
});
ストロングパラメータの設定
フォームから送信されるネストされたパラメータを安全に扱うために、以下のようにストロングパラメータを設定します。
devise_parameter_sanitizer.permit(:sign_up, keys: [
:name,
:representative,
:representative_image,
:contact_person,
:postal_code,
:prefecture,
:city,
:street_address,
:telephone,
:email,
:description,
:password,
:password_confirmation,
hos_dep_ids: [],
business_day_ids: [
hospital_business_hours_attributes: [] ※ここ重要
],
hospital_business_days_attributes: [
:id,
:business_day_id,
:_destroy,
hospital_business_hours_attributes: [
:id,
:open_time,
:close_time,
:_destroy
]
]
])
このストロングパラメータの設定は、hospital
オブジェクトに対する複雑なネストされた属性の更新を可能にします。特に、hospital_business_days_attributes
とhospital_business_hours_attributes
に対するネストされた更新を許可し、_destroy
キーを含めることで、関連オブジェクトの削除も可能にしています。
まとめ
Railsにおいて、hospital
とbusiness_day
の関係を管理し、動的に営業時間入力フォームを表示させる方法を解説しました。この実装では、モデルの関連付け、ビューの構築、JavaScriptによる動的なフォームの更新、そしてストロングパラメータの適切な設定が重要です。これらのステップに従うことで、ユーザーフレンドリーなフォームを実現し、アプリケーションのユーザーエクスペリエンスを向上させることができます。