Merey Nurlan
Merey Nurlan

Reputation: 305

What is the best way to implement belongs to many logic in Rails?

For example I have model Match and model Player. What I want is for Player to be able to participate in many matches.

So it should look smth like this:

@match_first = Match.first
@match_last  = Match.last

@match_first.players
#player1, player3, player4
@match_last.players
#player1, player4, player5

Both matches can have same players simultanously.

Upvotes: 0

Views: 103

Answers (2)

rmlockerd
rmlockerd

Reputation: 4126

Rails provides two ways to accomplish the many-to-many relationship. The first, which @zoot's answer describes, is has_many :through. This is a great option if the relationship is a Model in its own right (i.e., needs additional attributes or validations).

If the relationship between the two entities is direct such that you don't really need a third model, you can use the has_and_belongs_to_many association.

In your Match model:

has_and_belongs_to_many :players

In your Player model:

has_and_belongs_to_many :matches 

When you use has_and_belongs_to_many you do need to create a join table that holds the relationship. The migration for that (assuming a relatively recent version of Rails) might look like:

class CreateJoinTableMatchesPlayers < ActiveRecord::Migration
  def change
    create_join_table :matches_players, :users do |t|
      t.index [:match_id, :player_id], unique: true
    end
  end
end

There's a section in the Active Record Associations guide that talks about how to choose between the two approaches.

Upvotes: 1

zoot
zoot

Reputation: 36

In your Match model:

  has_many: :players, through: :appearances

In your Player model:

  has_many: :matches, through: :appearances
class Appearance < ActiveRecord::Base
  belongs_to :match
  belongs_to :player

You could have extra attributes on appearance like 'goals_scored'. The through model doesn't have to be called Appearance... it could be Attendance or MatchPlayer or PlayerMatch, but you can see that the last two names are constraining, because out of this association you can also see all the matches a player appeared in.

Upvotes: 2

Related Questions