From fae6332c366a6d769c3081aaa1d29706292ab039 Mon Sep 17 00:00:00 2001 From: Asish Kumar Date: Thu, 14 May 2026 09:23:06 +0530 Subject: [PATCH] Stop offering the schedule page when no schedule is published MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The home and splash page render a link to the schedule based purely on the `schedule_public` flag, even when an admin has not yet selected a schedule or scheduled any events. Following that link rendered the schedule view, which then failed inside `_carousel.html.haml` because `@rooms` (and the selected schedule) had no data — a 500 error instead of a graceful response. Treat `schedule_public` as an allowance rather than an unchecked control: introduce `Program#any_published_schedule?` (true only when the flag is on *and* there is at least one event in a selected schedule) and use it to decide whether to render the link from the home and splash pages. The schedule controller now returns 404 when no event has been scheduled, so bookmarked URLs surface as "not found" instead of an internal server error. --- app/controllers/schedules_controller.rb | 9 ++++---- app/models/program.rb | 17 +++++++++++++++ .../conferences/_conference_details.html.haml | 2 +- app/views/conferences/_program.haml | 2 +- spec/controllers/schedules_controller_spec.rb | 12 +++++++++++ spec/models/program_spec.rb | 21 +++++++++++++++++++ 6 files changed, 57 insertions(+), 6 deletions(-) diff --git a/app/controllers/schedules_controller.rb b/app/controllers/schedules_controller.rb index fd03abc6..bb4590cf 100644 --- a/app/controllers/schedules_controller.rb +++ b/app/controllers/schedules_controller.rb @@ -12,10 +12,11 @@ class SchedulesController < ApplicationController includes: [{ event: %i[event_type speakers submitter] }] ) - unless event_schedules - redirect_to events_conference_schedule_path(@conference.short_title) - return - end + # The +schedule_public+ flag opts a conference into displaying a schedule, + # but the schedule itself only exists once an admin has selected a schedule + # and at least one event has been scheduled. Return 404 to avoid rendering + # a broken page (or crashing) when the schedule has not yet been published. + return not_found if event_schedules.empty? respond_to do |format| format.xml do diff --git a/app/models/program.rb b/app/models/program.rb index d90f5961..cba455b4 100644 --- a/app/models/program.rb +++ b/app/models/program.rb @@ -163,6 +163,23 @@ class Program < ApplicationRecord (!conference.email_settings.program_schedule_public_subject.blank? && !conference.email_settings.program_schedule_public_body.blank?) end + ## + # Checks if there is a published schedule that should be displayed. + # A schedule is displayable only when the admin has enabled the + # +schedule_public+ flag *and* there is at least one event scheduled, + # either on the conference-wide selected schedule or on the selected + # schedule of any confirmed self-organized track. + # + # ====Returns + # * +true+ -> When the schedule is public and contains at least one event + # * +false+ -> Otherwise + def any_published_schedule? + return false unless schedule_public + return true if selected_schedule&.event_schedules&.exists? + + tracks.self_organized.confirmed.any? { |track| track.selected_schedule&.event_schedules&.exists? } + end + def languages_list languages.split(',').map {|l| ISO_639.find(l).english_name} if languages.present? end diff --git a/app/views/conferences/_conference_details.html.haml b/app/views/conferences/_conference_details.html.haml index 571cca4a..6f1c84d2 100644 --- a/app/views/conferences/_conference_details.html.haml +++ b/app/views/conferences/_conference_details.html.haml @@ -24,7 +24,7 @@ - if !@conference || @conference != conference - if conference.splashpage && conference.splashpage.public = link_to "View Conference", conference_path(conference.short_title), class: 'btn btn-default' - - if conference.program and conference.program.schedule_public + - if conference.program&.any_published_schedule? = link_to "Schedule", conference_schedule_path(conference.short_title), class: 'btn btn-default' - if conference.code_of_conduct.present? = link_to "Code of Conduct", code_of_conduct_conference_path(conference.short_title), class: 'btn btn-default' diff --git a/app/views/conferences/_program.haml b/app/views/conferences/_program.haml index 2ab2ef70..db79f480 100644 --- a/app/views/conferences/_program.haml +++ b/app/views/conferences/_program.haml @@ -24,7 +24,7 @@ - unless booths.blank? = render 'booths', booths: booths - - if conference.program.try(:schedule_public?) + - if conference.program&.any_published_schedule? .row .col-md-12 %p.cta-button.text-center diff --git a/spec/controllers/schedules_controller_spec.rb b/spec/controllers/schedules_controller_spec.rb index 2a6613b2..3eed79d7 100644 --- a/spec/controllers/schedules_controller_spec.rb +++ b/spec/controllers/schedules_controller_spec.rb @@ -26,5 +26,17 @@ describe SchedulesController do expect(response).to be_successful end end + + context 'when schedule is public but no events are scheduled' do + before :each do + conference.program.update!(schedule_public: true) + end + + it 'returns 404 instead of rendering a broken page' do + expect do + get :show, params: { conference_id: conference.short_title } + end.to raise_error(ActionController::RoutingError) + end + end end end diff --git a/spec/models/program_spec.rb b/spec/models/program_spec.rb index 23c42ff1..b96a2311 100644 --- a/spec/models/program_spec.rb +++ b/spec/models/program_spec.rb @@ -283,6 +283,27 @@ describe Program do end end + describe '#any_published_schedule?' do + let(:event) { create(:event, program: program) } + let(:schedule) { create(:schedule, program: program) } + let!(:event_schedule) { create(:event_schedule, event: event, schedule: schedule, start_time: DateTime.parse("#{Date.current + 1} 10:00").utc) } + + it 'returns false when schedule_public is disabled' do + program.update!(schedule_public: false, selected_schedule: schedule) + expect(program.any_published_schedule?).to be false + end + + it 'returns false when schedule_public is enabled but no schedule is selected' do + program.update!(schedule_public: true, selected_schedule: nil) + expect(program.any_published_schedule?).to be false + end + + it 'returns true when schedule_public is enabled and the selected schedule has events' do + program.update!(schedule_public: true, selected_schedule: schedule) + expect(program.any_published_schedule?).to be true + end + end + describe '#cfp' do it 'returns the cfp for events' do create(:cfp, cfp_type: 'events', program: program, end_date: Date.current + 1)