On Feb 5, 10:29 am, Mike <[email protected]> wrote: > Hi, > > I have an interesting dilemma, which is best shown through example. > Say I have Car and Part models which have a HABTM association. In > this case though, the Part class is an STL with Wheel and > SteeringWheel as models. Is there a way to setup the Car model with > both HABTM and has_one relationships to the same table? > > class Part < ActiveRecord::Base > has_and_belongs_to_many :cars > end > class Wheel < Part > end > class SteeringWheel < Part > # do I put a new association here?
You'd need to declare 'belongs_to :car' and add a corresponding car_id field to the parts table. > end > > class Car < ActiveRecord::Base > has_and_belongs_to_many :cars I'm guessing this is a typo, as you've got it as 'wheels' below. > has_one :steering_wheel > end > > This way, I could do something like so: > > car = Car.new > car.wheels << Wheel.new( :brand => 'Dunlop') > car.wheels << Wheel.new( :brand => 'Dunlop') > car.wheels << Wheel.new( :brand => 'Bridgestone' ) > car.wheels << Wheel.new( :brand => 'Bridgestone' ) > car.steering_wheel = SteeringWheel.new( :brand => 'Sparco' ) I'm not sure how useful the "car" analogy is here; it carries quite a bit of semantic baggage that may not apply to your real problem domain. Some notes about it anyways: - are the records in the 'Part' table intended to represent a *single* instance of a particular part or the generic class of all similar parts? It's unclear from the example above, as every instance of Car needs a different SteeringWheel record (has_one/belongs_to can only link one pair of records) but Car instances can share Wheels. In code: car1 = Car.new car2 = Car.new wheel = Wheel.new(:brand => 'Foo') steering_wheel = SteeringWheel.new(:brand => 'Bar') car1.wheels << wheel car1.save car2.wheels << wheel car2.save car1.wheels.first # => some Wheel object car2.wheels.first # => some Wheel object with the same ID as the first # so no problems there car1.steering_wheel = steering_wheel car1.save car2.steering_wheel = steering_wheel car2.save # and the gotcha: car1.reload car1.steering_wheel # => nil --- The other big issue with using STI here is that there really aren't that many properties in common between the two entities - manufacturer, perhaps? There certainly aren't many places where one could interchangeably use a steering wheel or a regular wheel... Again, this may be a specific issue with the "car" example, but it's worth checking into. If there's some overlap but a lot of difference, you may want to consider factoring the overlap into a module and avoiding the "everything and the kitchen sink" table that STI can lead to if used inappropriately. --Matt Jones -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.

