views:

17

answers:

1

Hi,

In my Rails app I have a has_many_through relation. I want to use the join model/table to store some data about the relation (how many times that particular relation is used, to be specific).

I'm writing an add-method on one of my classes which should check for any existing relation with the subject, update a counter on the relation if it exists or create it if it doesn't exist.

Example:

CoffeeDrinker is related to Coffee through Cup. Every time CoffeeDrinker takes a sip a counter on that particular Cup should be incremented. The first time CoffeeDrinker takes a sip, the Cup should be created and the counter initialized.

What is the easiest and/or most correct way to get a hold on the relation object?

+1  A: 

Either I'm not understanding your question or you're going to be surprised how obvious this is. You will have defined the relationship as so:

#coffee_drinker.rb
has_many :cups
has_many :coffees, :through => :cup

#cup.rb
belongs_to :coffee
belongs_to :coffee_drinker

#coffee.rb
has_many :cups
has_many :coffee_drinkers, :through => :cup

coffee_drinker.cups
coffee_drinker.coffees

coffee.cups
coffee.coffee_drinkers

#coffee_drinker.rb
after_save :update_cups_drunk

def update_cups_drunk
  cups.find_by_coffee_id(coffee_id).increment!(:count)
end

#maybe you don't have access to the coffee_id

def update_cups_drunk
  cups.find_by_coffee_id(coffees.last.id).increment!(:count)
end
mark
A combination, I guess :) Let me elaborate:Given a particular CoffeeDrinker and Coffee I need the actual Cup that relates the two. How do I get to that?Of course, I could do cup = Cup.find(:first, :conditions => ['coffee_drinker_id' => self.id, 'coffee_id' => coffee.id]) but it just doesn't feel right. Also, if there's a better way it would make my add and get methods easier to write.
fiskeben
By the way: the Coffees already exist in the database and won't be added once the app is running. Thus I will always be adding relations between existing objects and not create'ing.
fiskeben
Oh I get you. How about my edit? I take it you're finding or instantiating a coffee_drinker on coffee drink?
mark
That did it! Thanks a lot. I wasn't aware that I could use the find_by_* methods on collections but it makes perfect sense now.
fiskeben
That's great. Happy to help. :)
mark