0
0

Railsでの予約システムにおける非同期スロット更新とエラーハンドリング

Posted at

はじめに

今回は、Railsでの予約システムにおける非同期スロット更新の実装方法と、発生したエラーの解決方法について共有します。

問題点

予約システムの開発中に、日付を変更するたびにスロット情報を非同期で更新しようとしましたが、以下のエラーが発生しました。

ActiveRecord::RecordNotFound - Couldn't find Company with 'id'=undefined:
  app/controllers/reservations_controller.rb:207:in `update_slots'

解決方法

エラーの原因は、JavaScriptでcompany_idが正しく取得されず、リクエストにundefinedが渡されていたことです。以下の手順で解決しました。

ビューの修正

company_idを含むデータ属性を日付入力フィールドに追加します。

<%= form.date_field :date, id: 'for_customer_index_date_field', value: @date.strftime('%Y-%m-%d'), class: 'form-control', data: { company_id: @company.id } %> <!-- ここでdata-company-id属性を追加 -->

JavaScriptの修正

データ属性からcompany_idを取得し、リクエストに含めるようにします。

document.addEventListener('turbo:load', function() {
  const dateField = document.querySelector('#for_customer_index_date_field');
  if (dateField) {
    const companyId = dateField.dataset.companyId;
    const scheduleTitle = document.querySelector('.page-index');
    let companyName = '';

    if (scheduleTitle && scheduleTitle.textContent) {
      const match = scheduleTitle.textContent.match(/^(.*?)の/);
      if (match) {
        companyName = match[1];
      }
    }

    const debouncedFetch = debounce(function(date) {
      fetch(`/reservations/update_slots?date=${date}&company_id=${companyId}`, { // company_idをリクエストに含める
        headers: {
          'Accept': 'application/json',
          'X-Requested-With': 'XMLHttpRequest',
          'X-CSRF-Token': document.querySelector("[name='csrf-token']").content
        },
        credentials: 'include'
      })
      .then(response => response.json())
      .then(data => {
        if (data && data.services && data.time_slots !== undefined) {
          updateTable({ ...data, date });
        } else {
          console.error("Invalid data format received:", data);
        }
      })
      .catch(error => console.error('Error fetching data:', error));
    }, 500);

    dateField.addEventListener('input', function() {
      debouncedFetch(this.value);
    });
  }
});

コントローラーの修正

update_slotsアクションでcompany_idを正しく取得し、処理を行います。

def update_slots
  date = params[:date]
  @date = Date.parse(date)
  @company = Company.find(params[:company_id])
  @time_slots = generate_time_slots(@company)
  @non_business_day = ScheduleService.is_non_business_day?(@company, @date)
  @services = @company.services
  @service_availability = ScheduleService.calculate_availability(@company, @date, @services, @time_slots)
  response_data = {
    services: @services.map { |service|
      {
        name: service.name,
        duration: format_duration(service.duration),
        time_slots: @time_slots.map { |slot| { availability: @service_availability.dig(service.id, slot) || '-' } },
      }
    },
    time_slots: @time_slots,
    non_business_day: @non_business_day
  }
  render json: response_data
end
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0