Gareth Jones
Gareth Jones

Reputation: 1810

Rails - How to set up a relationship where has_many through could be multiple columns

I've been out of the rails dev world for a little while and am a bit rusty when it comes to setting up relationships and joins between tables, so apologies if this is a very simple question.

I can achieve it with the following query, but it's far from ideal.

@matches = Match.where(home_team_id: @team.id) || Match.where(away_team_id: @team.id))

So what's the recommended way to set up my models and relationships to achieve the above behaviour?

Thanks in advance!

Upvotes: 1

Views: 1187

Answers (3)

Kewei Jiang
Kewei Jiang

Reputation: 163

This is inspired by @Joel_Blum's answer. I think it's a bit cleaner and expands the utility through home_matches and away_matches scopes:

 class Match < ApplicationRecord
     belongs_to :home_team, class_name: "Team"
     belongs_to :away_team, class_name: "Team"
 end

 class Team < ApplicationRecord
     has_many :home_matches, foreign_key: :home_team_id, class_name: "Match"
     has_many :away_matches, foreign_key: :away_team_id, class_name: "Match"
 
     def matches
         home_matches.or(away_matches)
     end
 end

Upvotes: 3

Joel Blum
Joel Blum

Reputation: 7878

This is a possible model setup

 class Match < ApplicationRecord
     belogns_to :home_team, class_name: "Team"
     belongs_to :away_team, class_name: "Team"
 end

 class Team < ApplicationRecord
    has_many :matches,-> {
      unscope(:where).where(home_team_id: self.id).or(where(away_team_id: self.id))
    }
 end

And now @team.matches should just work. The only tricky part is getting the has_many to work with 2 foreign keys by doing unscope(:where)

Upvotes: 0

Ben Trewern
Ben Trewern

Reputation: 1740

I've done similar with the following in the model:

def matches
  Match.where('home_team_id = ? OR away_team_id = ?', self.id, self.id)
end

which at least gives you a scope. Then in your controller:

@matches = @team.matches

I'd be interested in any other ideas.

Upvotes: 0

Related Questions