Stop offering the schedule page when no schedule is published

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.
This commit is contained in:
Asish Kumar 2026-05-14 09:23:06 +05:30
parent c8e6fabed1
commit fae6332c36
6 changed files with 57 additions and 6 deletions

View file

@ -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

View file

@ -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

View file

@ -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'

View file

@ -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

View file

@ -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

View file

@ -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)