Help with model relationship for Product/Bill of Materials

I am struggling to find the best way to set up relationships to
achieve this so that it fits the rails idioms.

I have a table of products and I want to be able to create a bill of
materials for a product…

So a product can either be a single item, or a package consisting of
several other products.

I have created a table:


class BomItem < ActiveRecord::Base

belongs_to :product

belongs_to :component,
:class_name=>‘Product’,
:foreign_key=>‘component_id’

validates_numericality_of :quantity

So for a product p, I can have:
bom=p.bom_items
item=bom[0] etc

and for each item I can have:
c=item.component (which is a product)

Now for c I would like to be able to ask
c.component_of

at the moment, I can only think to set up a product method

Perhaps that is the best way to do it, but I just feel I am not
modeling this in the best way. I also want to make sure a product
cannot have a bom and be a component in the same bom - since that is
circular

If any experts in data modeling have any suggestions or advice I’d be
grateful

ps. I did have one bright idea to sub class product into component
and packet, which worked really well from console tests, but messed up
my Product views because although @product=Product.find id, the url
for product_path(@product) becomes packet path if it has type=‘Packet’
and of course there is no such route. That did my head in so I
dropped the idea.

Tonypm

Tony,
I’m currently working on the same thing but have decided to make BOM’s
a separate entity and not an item in the item file. Thus I have an
Assembly table that has many Assyitems. These Assytitems hold foreign
keys to the Item table. This works well when users don’t have to do
nested BOM’s.
Kathleen

Keeping your BomItem model pretty much as is you could have

class Product …
has_many :bom_items
has_many :components, :through => :bom_items
end

This gives you what you’ve already got.

Then you can say

has_many :bom_uses, :foreign_key => ‘component_id’, :class_name =>
‘BomItem’
has_many :uses, :through => :bom_uses, :source => :product

(please think of better names than I have :slight_smile:
Then given a production, p.components are the products it is made of,
and p.uses is the products that uses it as a component

Fred

Kathleen,

thanks for the suggestion. I thought about pulling BOM out to a
separate model that would be used to reference the BOM Items. I went
backwards and forwards a few times and decided to try it with just the
bom_items and see if I was losing any functionality. Still putting
together the view to allow BOMs to be created for a product, I will
see how it works out.

Thanks
Tony