I was previously using has_and_belongs_to_many, and have converted to has_many :through. Here's how it looks for a list of games that can have many users playing. With this, I can do game.users and user.games....:
class Game < ActiveRecord::Base
has_many :game_users, :dependent => :destroy
has_many :users, :through => :game_users, :uniq => true
end
class User < ActiveRecord::Base
has_many :game_users, :dependent => :destroy
has_many :games, :through => :game_users, :uniq => true
end
class GameUser < ActiveRecord::Base
belongs_to :game
belongs_to :user
end
And my database migration for the join table:
create_table :game_users, :id => false do |t|
t.column :game_id, :integer
t.column :user_id, :integer
t.column :player_index, :integer
end
I'm not quite sure I get all this, please help me check my facts:
Is the dependent => :destroy correct? I want the 'game_users' join table entry to be deleted if either the game or the user is destroyed - but I don't want users to be deleted if games are deleted and vice versa..... ?
The uniq field is supposed to say that games contain only unique users, and the users only contain unique games. Is that correct?
The database migration as before has :id => false. Is that still the right thing to do? I tried in the console destroying a game, and got complaints about the missing id... so I'm guessing not and trying to understand why.
I find rails active record associations very confusing. I guess they aren't supposed to be!
1: Yes, that's correct
2: From the documentation on uniq:
If true, duplicates will be omitted from the collection. Useful in conjunction with :through.
So, yes, if you aim is not get the same game in User's games-collection nor the same user in Game's users-collection, that's correct. It's all explained here.
It will not, however, prevent duplicate GameUsers from being created. For that, you'd need to use validates_ uniqueness _of in the GameUser-model:
class GameUser < ActiveRecord::Base
validates_uniqueness_of :game_id, :scope => :user_id
end
3: No, you don't want to use :id => false any more. By switching from has_and_belongs_to_many to has_many :through, you have promoted your many-to-many join-table to a full model - GameUser - which requires its own id.
While it is old, this is still a good article for understanding has_many :through.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With