Simplify default beamer handling

This commit is contained in:
Daniel Schädler 2026-04-16 13:02:40 +02:00
parent ea173be88a
commit 761bb8daea
10 changed files with 72 additions and 25 deletions

View File

@ -20,7 +20,7 @@ class BeamersController < ApplicationController
# GET /tournaments/:tournament_id/beamers/by_name?name=beamername
def by_name
beamer = @tournament.beamers.find_by(name: params[:name])
beamer ||= @tournament.beamers.default_beamer.first
beamer ||= @tournament.beamers.find_by(name: Beamer::DEFAULT_NAME)
if beamer
render json: beamer
else
@ -64,6 +64,6 @@ class BeamersController < ApplicationController
end
def beamer_params
params.permit(:name, :display_state, :is_default, :qr_code_url, :logo_url)
params.permit(:name, :display_state, :qr_code_url, :logo_url)
end
end

View File

@ -1,6 +1,7 @@
# frozen_string_literal: true
class Beamer < ApplicationRecord
DEFAULT_NAME = 'default'
DISPLAY_STATES = %w[
matches_all matches_in_progress matches_upcoming matches_not_started
matches_finished groups between_games during_game
@ -11,7 +12,5 @@ class Beamer < ApplicationRecord
validates :name, presence: true, uniqueness: { scope: :tournament_id }
validates :display_state, presence: true, inclusion: { in: DISPLAY_STATES }
scope :default_beamer, -> { where(is_default: true) }
delegate :owner, to: :tournament
end

View File

@ -16,6 +16,7 @@ class Tournament < ApplicationRecord
alias_attribute :owner, :user
after_initialize :generate_code
after_create_commit :ensure_default_beamer!
def matches
[stages.map(&:matches), stages.map { |s| s.groups.map(&:matches) }].flatten
@ -50,4 +51,10 @@ class Tournament < ApplicationRecord
errors.add(:playoff_teams_amount,
'playoff_teams_amount needs to be a positive power of two')
end
def ensure_default_beamer!
beamers.find_or_create_by!(name: Beamer::DEFAULT_NAME) do |beamer|
beamer.display_state = 'matches_all'
end
end
end

View File

@ -1,5 +1,5 @@
# frozen_string_literal: true
class BeamerSerializer < ApplicationSerializer
attributes :name, :display_state, :is_default, :qr_code_url, :logo_url
attributes :name, :display_state, :qr_code_url, :logo_url
end

View File

@ -0,0 +1,40 @@
# frozen_string_literal: true
class BackfillDefaultBeamersByName < ActiveRecord::Migration[7.0]
DEFAULT_BEAMER_NAME = 'default'
class MigrationTournament < ApplicationRecord
self.table_name = 'tournaments'
end
class MigrationBeamer < ApplicationRecord
self.table_name = 'beamers'
end
def up
MigrationTournament.find_each do |tournament|
beamers = MigrationBeamer.where(tournament_id: tournament.id)
next if beamers.exists?(name: DEFAULT_BEAMER_NAME)
legacy_default = beamers.find_by(is_default: true)
if legacy_default
legacy_default.update_columns(name: DEFAULT_BEAMER_NAME)
else
MigrationBeamer.create!(
tournament_id: tournament.id,
name: DEFAULT_BEAMER_NAME,
display_state: 'matches_all'
)
end
end
end
def down
MigrationBeamer.where(name: DEFAULT_BEAMER_NAME).where.not(tournament_id: nil).find_each do |beamer|
next unless MigrationBeamer.where(tournament_id: beamer.tournament_id).count == 1
beamer.delete
end
end
end

View File

@ -6,8 +6,8 @@ RSpec.describe BeamersController, type: :controller do
before do
@tournament = create(:tournament)
@owner = @tournament.owner
@default_beamer = @tournament.beamers.find_by!(name: Beamer::DEFAULT_NAME)
@beamer = create(:beamer, tournament: @tournament)
@default_beamer = create(:default_beamer, tournament: @tournament)
end
describe 'GET #index' do
@ -47,18 +47,18 @@ RSpec.describe BeamersController, type: :controller do
expect(response).to be_successful
body = deserialize_response response
expect(body[:name]).to eq(@default_beamer.name)
expect(body[:is_default]).to be true
end
it 'falls back to default beamer when name param is missing' do
get :by_name, params: { tournament_id: @tournament.to_param }
expect(response).to be_successful
body = deserialize_response response
expect(body[:is_default]).to be true
expect(body[:name]).to eq(Beamer::DEFAULT_NAME)
end
it 'returns 404 when no beamers exist at all' do
it 'returns 404 when all beamers were deleted' do
empty_tournament = create(:tournament)
empty_tournament.beamers.destroy_all
get :by_name, params: { tournament_id: empty_tournament.to_param, name: 'anything' }
expect(response).to have_http_status(:not_found)
end
@ -66,7 +66,7 @@ RSpec.describe BeamersController, type: :controller do
describe 'POST #create' do
let(:valid_params) do
{ name: 'new-beamer', display_state: 'groups', is_default: false }
{ name: 'new-beamer', display_state: 'groups' }
end
context 'as owner' do

View File

@ -259,6 +259,14 @@ RSpec.describe TournamentsController, type: :controller do
expect(included_teams).to match_array(@teams)
end
it 'creates a default beamer automatically' do
post :create, params: create_playoff_tournament_data
body = deserialize_response response
tournament = Tournament.find(body[:id])
expect(tournament.beamers.pluck(:name)).to include(Beamer::DEFAULT_NAME)
end
context 'with parameter group_stage=true' do
before do
post :create, params: create_group_tournament_data

View File

@ -4,12 +4,10 @@ FactoryBot.define do
factory :beamer do
sequence(:name) { |n| "beamer-#{n}" }
display_state { 'matches_all' }
is_default { false }
tournament
factory :default_beamer do
name { 'default' }
is_default { true }
end
end
end

View File

@ -36,19 +36,6 @@ RSpec.describe Beamer, type: :model do
it { should belong_to :tournament }
end
describe 'scopes' do
describe '.default_beamer' do
it 'returns only default beamers' do
tournament = create(:tournament)
default = create(:default_beamer, tournament: tournament)
create(:beamer, tournament: tournament)
result = tournament.beamers.default_beamer
expect(result).to contain_exactly(default)
end
end
end
describe '#owner' do
it 'delegates to tournament' do
beamer = create(:beamer)

View File

@ -32,6 +32,14 @@ RSpec.describe Tournament, type: :model do
it { should have_many :beamers }
end
describe 'default beamer' do
it 'creates a default beamer automatically' do
tournament = create(:tournament)
expect(tournament.beamers.pluck(:name)).to include(Beamer::DEFAULT_NAME)
end
end
describe '#matches' do
context 'group stage tournament' do
before do