Associating 2 Users in 1 modeled join table

Chris Bloom wrote:

I'm having trouble getting this right (ActiveRecord associations are my weakness). Given two models:

Racers:   :racer_id   :name

TandemRacers:   :racer_1_id   :racer_2_id   :start (datetime)   :return (datetime)

How do I associate the models such that I can call a Riders coriders, and also see what riders have ridden on a tandem? Not all Racers will ride tandem, and those that do won't ride them for the whole race. TandemRacers will have it's own controller.

So far I have: class Racer < ActiveRecord::Base   has_and_belongs_to_many :coracers,     :class_name => "Racer",     :join_table => "tandem_racers",     :association_foreign_key => "racer_2_id",     :foreign_key => "racer_1_id" end

I'm not sure what should in the TandemRacers model on the other end though.

Is there really an "ordering" to the pairings. E.g. what does it mean for a racer to be racer_1 or racer_2?

[mailto:rubyonrails-talk@googlegroups.com] On Behalf Of Chris Bloom

The problem that I'm facing is that I will need to be able to know:

1. If a rider was part of a tandem team, and if so how many times 2. The riders s/he was partnered with.<

Would it help to introduce a Bike model? Some Bikes have two Riders; some have one.

///ark

Would it help to introduce a Bike model? Some Bikes have two Riders; some have one.

So, it's assumed from the Racers table that they each have a one-rider bike. And there is only one tandem bike that will be shared - two riders at a time - and that's what I am most interested in tracking - what two riders were on the bike. I suppose that it is less important to know who was paired with who, but I would like to know who rode the tandem bike at any given time, and perhaps how many times (though this will probably be 0 or 1)

If a Bike has_many Racers, then you could avoid the racer_1 and racer_2 columns.

///ark

Seems to me you need a model for a Rider, and another model for an "Event". The "Event" would represent a specific instance of a bike running a race, so it would have dates, times, etc.

Since an "Event" (not sure that's the best name) could have 1 or 2 riders, and any given rider could participate in multiple "Events", it looks like a habtm relationship to me.

   riders <-- events_riders --> events

Seems to me you need a model for a Rider, and another model for an "Event". The "Event" would represent a specific instance of a bike running a race, so it would have dates, times, etc.

Since an "Event" (not sure that's the best name) could have 1 or 2 riders, and any given rider could participate in multiple "Events", it looks like a habtm relationship to me.

  riders <-- events_riders --> events

I think this is similar to what I was thinking about Bike, except that in my case, I would flatten the habtms by discriminating by Race (sorry, I just couldn't resist!):

Race has_many Bikes has_many Racers

///ark

I'm thinking something like:

class TandemRide   has_and_belongs_to_many :riders   # work out how to constrain/validate this to only two end

class Rider < ActiveRecord::Base

  has_and_belongs_to_many :tandem_rides

# Theres probably a better way to do this with sql, but if there aren't too many riders # and rides this would probably work   def co_riders_with_duplicates       tandem_rides.inject() {|res, p| res << p.riders - [self])   end

  def co_riders     co_riders_with_dupicates.uniq   end end

Rick Denatale wrote: > I'm thinking something like: > > > class TandemRide > has_and_belongs_to_many :riders > # work out how to constrain/validate this to only two > end > > class Rider < ActiveRecord::Base > > has_and_belongs_to_many :tandem_rides > > # Theres probably a better way to do this with sql, but if there > aren't too many riders > # and rides this would probably work > def co_riders_with_duplicates > tandem_rides.inject() {|res, p| res << p.riders - [self]) > end > > def co_riders > co_riders_with_dupicates.uniq > end > end > -- > Rick DeNatale > > My blog on Ruby > http://talklikeaduck.denhaven2.com/

Hmm, that looks interesting. But does that put me back to having two entries in tandemride for each pairing, A -> B and B -> A? If so, so be it. That's easy enough to do and build constraints for.

the tandemride table really only needs an id field, at least with the requirements you've given.

You'll need a riders_tandem_rides table to represent the habtm relationships

Now lets say we had the following tandem rides

Joe and Sally Joe and Sam Sally and Sam

riders table id Name .... 1 Joe 2 Sally 3 Sam

tandem_rides table id 1 2 3

iders_tandem_rides table rider_id tandem_ride_id 1 1 1 2 2 1 2 3 3 2 3 3

Also, what does the "- [self]" part of the inject block do?

It removes the rider himself from the list of his co_riders.

Mind you, none of this is tested code.