module Tournaments class FillKnockoutSources def self.call(tournament) new(tournament).call end def initialize(tournament) @tournament = tournament end def call @tournament.matches.find_each do |match| next if match.home_source_kind.blank? && match.away_source_kind.blank? home = resolve(match, :home) away = resolve(match, :away) attrs = {} attrs[:home_participant] = home if home && match.home_participant_id.blank? attrs[:away_participant] = away if away && match.away_participant_id.blank? match.update!(attrs) if attrs.any? end end private def resolve(match, side) kind = match.public_send("#{side}_source_kind") case kind when "winner_match" source = Match.find_by(id: match.public_send("#{side}_source_match_id")) source&.winner_participant when "group_rank" group = TournamentGroup.find_by(id: match.public_send("#{side}_source_group_id")) rank = match.public_send("#{side}_source_rank").to_i return nil unless group && rank.positive? Tournaments::Standings.call(group)[rank - 1]&.participant end end end end