class MakeMoveCommand attr :game, :game_id, :player, :position, :repository def initialize(game_id:, repository:, player:, position:) @game_id = game_id @player = player @position = position @repository = repository end def apply! @game = repository.find(game_id) validate_game_is_in_progress validate_player validate_tile game.apply_move! position: position end def tile game.fetch_tile position end def validate_game_is_in_progress raise BadMove, "Game has already ended!" if game.finished? end def validate_player raise BadMove, "It is #{game.player}'s turn" unless player == game.player end def validate_tile unless tile == :free raise BadMove, "Tile at #{position} is already occupied!" end end end