前回の記事
ScheduleService の実装詳細
前回の記事で概要を説明した後、このパートでは ScheduleService
の具体的なメソッド実装と、コントローラーでの利用方法を深掘りします。
1. ScheduleServiceのメソッド実装
ScheduleService
クラスの中核となるメソッドは、特定の日に提供可能なスタッフのスケジュールを取得し、それを元に利用可能な時間スロットの状況を分析します。
build_staff_schedule_map メソッド
このメソッドは、指定されたサービスを提供可能なスタッフのスケジュールをマッピングします。スタッフごとにその日のスケジュールを配列として保存します。
def self.build_staff_schedule_map(working_staffs, service, date)
working_staffs.each_with_object({}) do |staff, map|
if staff.services.include?(service)
map[staff.id] = staff.schedules.select { |sch| sch.date == date }
end
end
end
analyze_time_slots メソッド
各時間スロットに対して、提供可能なスタッフ数を計算し、それに基づいて時間スロットの状態を評価します。ここではシンプルに、スタッフが1人のみ利用可能な場合は△、複数いる場合は○、いない場合は×としています。
def self.generate_time_slots_availability(staff_schedule_map, time_slots)
time_slots.each_with_object({}) do |slot, inner_hash|
available_staff_count = staff_schedule_map.count do |_, schedules|
schedules.any? do |schedule|
start_time = schedule.start_time.strftime("%H:%M")
end_time = schedule.end_time.strftime("%H:%M")
time_in_slot = start_time <= slot && slot < end_time
time_unavailable = schedule.time_tables.any? { |tt| !tt.available && tt.start_time.strftime("%H:%M") <= slot && tt.end_time.strftime("%H:%M") > slot }
time_in_slot && !time_unavailable
end
end
inner_hash[slot] = case available_staff_count
when 0 then '×'
when 1 then '△'
else '○'
end
end
end
2. コントローラでのScheduleServiceの利用
ReservationsController
と SchedulesController
で ScheduleService
を利用する例を示します。このサービスを利用することで、コントローラはビジネスロジックから解放され、主にデータの受け渡しと応答の管理に集中できます。
# ReservationsController
def confirm
@company = Company.find(params[:company_id])
@date = params[:date] || Date.today
@services = @company.services
@time_slots = generate_time_slots(@company)
@service_availability = ScheduleService.calculate_availability(@company, @date, @services, @time_slots)
end
# SchedulesController
def index
@company = Company.find(params[:company_id])
@date = params[:date] || Date.today
@services = @company.services
@time_slots = generate_time_slots(@company)
@service_availability = ScheduleService.calculate_availability(@company, @date, @services, @time_slots)
end
まとめ
ScheduleService
の導入により、アプリケーションのコードベースはより整理され、各コンポーネントの責任が明確になりました。サービスオブジェクトの導入は、特に大規模なアプリケーションや複数のコンポーネント間で共有される複雑なビジネスロジックを持つ場合に有効です。これにより、アプリケーションの拡張性と保守性が向上し、将来の開発が容易になります。