Joining three objects uniquely using :has_many

I've confused myself.

I have three objects: level, product, part. Together they classify a repair type.

- Replacing a part in a product has a level of difficulty associated with it. - The same part replaced in a different product has a different level of difficulty.

How can I model an association among these?

I have created a join model, "Repair class," and connected all three using :has_many through. However, this does not prevent multiple records where the part and product stay the same, but the level changes. In other words, I end up with multiple levels assigned to the same part/product combination which does not happen in the real world.

What's the best way to proceed?

Evan

I've confused myself.

I have three objects: level, product, part. Together they classify a repair type.

- Replacing a part in a product has a level of difficulty associated with it. - The same part replaced in a different product has a different level of difficulty.

How can I model an association among these?

I have created a join model, "Repair class," and connected all three using :has_many through. However, this does not prevent multiple records where the part and product stay the same, but the level changes. In other words, I end up with multiple levels assigned to the same part/product combination which does not happen in the real world.

You might want to describe exactly what join model you have created

Personally my instinct would be to have a unique index on the join
table enforcing that there is only one entry for each part/product pair

Fred

My join model is "Repair class." Its attributes are:

- id (PK) - level_id (FK) - product_id (FK) - part_id (FK)

So I could create a unique index consisting of product_id, part_id. Is it possible to then create a unique index consisting of level_id and the other index? I am using MySQL currently.

I just tried this code and was still able to create records with different levels for the same part/product combination.

class RepairClass < ActiveRecord::Base   belongs_to :level   belongs_to :product   belongs_to :part

  validates_presence_of :level_id, :product_id, :part_id   validates_uniqueness_of :level_id, :scope => [ :product_id, :part_id ] end

I'm not sure I'm 100% clear, but it sounds like you are saying that a Repair may only have one combination of Part/Product, and it just so happens that this combination implies a Level. To me the validation would be:

class Repair < ActiveRecord::Base   belongs_to :level   belongs_to :product   belongs_to :part

  validates_presence_of :level_id, :product_id, :part_id   validates_uniqueness_of :part_id, :scope => [:product_id] end

Assuming I understand the problem, I think your confusion stems from the fact that the level isn't part of what defines a Repair, its simply an attribute of the Repair. It is really the Part and the Product that you should be concerned with.

Andrew,

Your last paragraph helps clarify it a little bit. I think you are correct in that I am chasing the wrong thing. I think that stems from not fully understanding the scope option of validates_uniqueness_of. The documentation for it is not clear.

Evan

Andrew,

Changing the scope of validates_uniqueness_of to product_id solved my problem. Thank you.

Evan