ruby-on-rails

Let users join multiple leagues (groups) and switch between them


I'm creating an application to store played FIFA Games and build a private leaderboard with friends.

I managed to add a user to a league (private group) but now I want to let users join multiple leagues and easily switch between them.

I've added a league_id to games and to users.

When loading the leaderboard I'm only showing the users that match current_user.league_id and for the wins and losses I'm only counting the games with that match current_user.league_id.

This works perfectly, however a user should be able to join another league and switch easily between them. I was thinking creating another field to users that stores a collection of all joined leagues and add an action to change the active_league_id.

Can someone point me in the right direction here?

class User < ActiveRecord::Base
    
    devise :registerable, :confirmable
    devise :omniauthable, :omniauth_providers => [:facebook]
     
    #RELATIONS SINGLE GAMES
    
    has_many :home_games,    class_name: 'Game', foreign_key: 'home_team_user_id'
    has_many :away_games, class_name: 'Game', foreign_key: 'away_team_user_id'
    
    #RELATIONS MULTI GAMES
    
    has_many :first_home_games,    class_name: "Multiplayergame", foreign_key: "home_team_first_user_id"
    has_many :second_home_games,    class_name: "Multiplayergamer", foreign_key: "home_team_second_user_id"
    
    has_many :first_away_games, class_name: "Multiplayergame", foreign_key: "away_team_first_user_id"
    has_many :second_away_games, class_name: "Multiplayergame", foreign_key: "away_team_second_user_id"
    
    #RELATIES SCORE CLASSEREN SINGLE GAMES 
    
    has_many :wins, class_name: 'Game', foreign_key: 'winner_id'
    has_many :losses, class_name: 'Game', foreign_key: 'loser_id'
    
    has_many :bonusses, class_name: 'Game', foreign_key: 'bonus_id'
    has_many :loserbonusses, class_name: 'Game', foreign_key: 'bonus_loser_id'
    
    has_many :firstdraws, class_name: 'Game', foreign_key: 'first_draw_id'
    has_many :seconddraws, class_name: 'Game', foreign_key: 'second_draw_id'

    
    #RELATIES SCORE CLASSEREN MULTI GAMES 
    
    has_many :firstwins, class_name: 'Multiplayergame', foreign_key: 'winner_first_id'
    has_many :secondwins, class_name: 'Multiplayergame', foreign_key: 'winner_second_id'
    has_many :firstlosses, class_name: 'Multiplayergame', foreign_key: 'loser_first_id'
    has_many :secondlosses, class_name: 'Multiplayergame', foreign_key: 'loser_second_id'
    
    has_many :firstbonusses, class_name: 'Multiplayergame', foreign_key: 'bonus_first_id'
    has_many :secondbonusses, class_name: 'Multiplayergame', foreign_key: 'bonus_second_id'
    has_many :firstloserbonusses, class_name: 'Multiplayergame', foreign_key: 'bonus_first_loser_id'
    has_many :secondloserbonusses, class_name: 'Multiplayergame', foreign_key: 'bonus_second_loser_id'
    
    has_many :firstmultidraws, class_name: 'Multiplayergame', foreign_key: 'first_multidraw_id'
    has_many :secondmultidraws, class_name: 'Multiplayergame', foreign_key: 'second_multidraw_id'
    has_many :thirdmultidraws, class_name: 'Multiplayergame', foreign_key: 'third_multidraw_id'
    has_many :fourthmultidraws, class_name: 'Multiplayergame', foreign_key: 'fourth_multidraw_id'
    
    belongs_to :league
    
    has_one :league_admin, class_name: 'League', foreign_key: 'league_admin_id'
    
##############################################################################################
    
    ### TOTAL WINS CURRENT LEAGUE SINGLE PLAYER
    
    def current_league_wins
        wins.where(:league_id => self.league_id).count
    end
    
    #### TOTAL LOSSES CURRENT LEAGUE SINGLE PLAYER
    
    def current_league_losses
        losses.where(:league_id => self.league_id).count
    end
    
    #### TOTAL DRAWS CURRENT LEAGUE SINGLE PLAYER
    
    def draws
        firstdraws.where(:league_id => self.league_id).count + seconddraws.where(:league_id => self.league_id).count
    end
    
#####################################################################################################    
    #### TOTAL WINS CURRENT LEAGUE MULTIPLAYER
    
    def current_league_multi_wins
        firstwins.where(:league_id => self.league_id).count + secondwins.where(:league_id => self.league_id).count
    end
    
    
    #### TOTAL LOSSES CURRENT LEAGUE MULTIPLAYER
    
    def current_league_multi_losses
        firstlosses.where(:league_id => self.league_id).count + secondlosses.where(:league_id => self.league_id).count
    end
    
    #### TOTAL DRAWS CURRENT LEAGUE MULTIPLAYER
    
    def multidraws
    firstmultidraws.where(:league_id => self.league_id).count + secondmultidraws.where(:league_id => self.league_id).count + thirdmultidraws.where(:league_id => self.league_id).count + fourthmultidraws.where(:league_id => self.league_id).count
    
    end

Controller scoreboard:

class ScoreboardController < ApplicationController
    before_action :authenticate_user!
    
    #LAAD ALLE USERS GERANSCHIKT VOLGENS SCORE
    
    def index
        @users = User.where(:league_id => current_user.league_id).sort_by(&:score).reverse
        
  
        
    end
    
end

What I need to achieve is that users can easily switch between the joined leagues and that if a user changes leagues he still appears in all the leaderboards. If a user changes league now he's not in that leaderboard any more until he rejoins, which is normal since his league_id changes.


Solution

  • I think what you're looking for is a has_and_belongs_to_many relation between your Users and your Leagues.

    class User < ActiveRecord::Base
      has_and_belongs_to_many :leagues
    end
    
    class League < ActiveRecord::Base
      has_and_belongs_to_many :users
    end
    

    This will create a table called leagues_users which will contain foreign keys to your leagues and users tables respectively.

    You can easily switch between the league you want to check out by looking at current_user.leagues.

    Edit

    Regarding your scoreboard controller I'd say it makes more sense to set a scoreboard based on and not based on the current user (if users can belong to several leagues).

    Something like this:

    class Scoreboard < ActiveRecord::Base
      has_one :league  
    end
    
    def ScoreboardController < ApplicationController
    
      def show
        @scoreboard = Scoreboard.find(params[:id])
        # and access the users like so:
        # @scoreboard.league.users
      end
    
    end