diff --git a/app/serializers/live_match_serializer.rb b/app/serializers/live_match_serializer.rb index 8932c2e..3b0f27a 100644 --- a/app/serializers/live_match_serializer.rb +++ b/app/serializers/live_match_serializer.rb @@ -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 diff --git a/doc/tournament_live_updates.md b/doc/tournament_live_updates.md index 6383248..9d8f9f4 100644 --- a/doc/tournament_live_updates.md +++ b/doc/tournament_live_updates.md @@ -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 diff --git a/spec/controllers/matches_controller_spec.rb b/spec/controllers/matches_controller_spec.rb index 522d58f..b7429a4 100644 --- a/spec/controllers/matches_controller_spec.rb +++ b/spec/controllers/matches_controller_spec.rb @@ -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 diff --git a/spec/services/tournament_live_payload_spec.rb b/spec/services/tournament_live_payload_spec.rb index 6e9d681..3d3502e 100644 --- a/spec/services/tournament_live_payload_spec.rb +++ b/spec/services/tournament_live_payload_spec.rb @@ -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