Keep group identity in live match payload

This commit is contained in:
Daniel Schädler 2026-04-24 16:12:43 +02:00
parent 4dc8198bc2
commit 35e66f6aeb
4 changed files with 38 additions and 5 deletions

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true
class LiveMatchSerializer < ApplicationSerializer
attributes :position, :state, :teams
attributes :position, :state, :teams, :group, :stage
has_many :match_scores
@ -13,4 +13,24 @@ class LiveMatchSerializer < ApplicationSerializer
}
end
end
def group
return nil if object.group.nil?
{
id: object.group.id,
number: object.group.number
}
end
def stage
stage = object.stage || object.group&.stage
return nil if stage.nil?
{
id: stage.id,
level: stage.level,
state: stage.state
}
end
end

View File

@ -91,6 +91,8 @@ Use this when page only needs match cards/list updates:
- match id
- position
- state
- group identity
- stage identity
- teams
- score rows
@ -136,6 +138,15 @@ Payload:
"id": 456,
"position": 0,
"state": "in_progress",
"group": {
"id": 44,
"number": 1
},
"stage": {
"id": 33,
"level": -1,
"state": "in_progress"
},
"teams": [
{
"id": 10,
@ -234,7 +245,7 @@ Recommended update handling:
- do not patch a single nested field from websocket payload
- replace the full snapshot for that channel/filter
- use `match.id`, `team.id`, and `match_score.id` as stable keys
- use `match.id`, `group.id`, `stage.id`, `team.id`, and `match_score.id` as stable keys
- tolerate duplicate payloads
- tolerate fast sequences like score update followed by match finish

View File

@ -47,7 +47,7 @@ RSpec.describe MatchesController, type: :controller do
get :index, params: { tournament_id: @tournament.to_param }
match = deserialize_response(response).first
expect(match.keys).to match_array(%i[id position state teams match_scores])
expect(match.keys).to match_array(%i[id position state teams match_scores group stage])
expect(match[:teams]).to all(include(:id, :name))
end
end

View File

@ -21,14 +21,16 @@ RSpec.describe 'Tournament live payloads' do
describe TournamentMatchesPayload do
it 'serializes only match live fields used by matches API and websocket' do
tournament = create(:group_stage_tournament, match_factory: :filled_group_match)
match = tournament.matches.first
match = tournament.stages.find { |stage| stage.level == -1 }.groups.first.matches.first
payload = described_class.build(tournament)
serialized_match = payload.find { |candidate| candidate[:id] == match.id }
expect(serialized_match.keys).to match_array(%i[id position state teams match_scores])
expect(serialized_match.keys).to match_array(%i[id position state teams match_scores group stage])
expect(serialized_match[:state]).to eq(match.state)
expect(serialized_match[:position]).to eq(match.position)
expect(serialized_match.dig(:group, :id)).to eq(match.group_id)
expect(serialized_match.dig(:stage, :id)).to eq(match.group.stage_id)
expect(serialized_match[:teams].map { |team| team[:id] }).to match_array(match.teams.map(&:id))
expect(serialized_match[:match_scores].map { |score| score[:team][:id] }).to match_array(match.teams.map(&:id))
end