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.