has_many :through usage, simple, beginner question

大城市里の小女人 提交于 2019-12-08 17:35:29

First a question: What is your relation between Product and LineItem: Has 1 product many line items or is 1 and the same line item referenced in many products? The rest of this answer is based on the assumption that every product should have multiple line items.

I think your models should be defined like that:

# No change
Class Invoice < ActiveRecord::Base
  has_many :products
  has_many :line_items, :through => :products
end

# Changed the relation to :line_items
Class Product < ActiveRecord::Base
  belongs_to :invoice
  has_many :line_items
end

class LineItem < ActiveRecord::Base
  belongs_to :products
  # The following then does not make sense
  ##has_many :invoices, :through => :invoices
end

why did you choose this structure? in such cases i usually do

Class Invoice < ActiveRecord::Base
  has_many :line_items
  has_many :products, :through => :line_items
end

Class Product < ActiveRecord::Base
  has_many :line_items
  # if you need
  has_many :products, :through => :line_items
end

class LineItem < ActiveRecord::Base
  belongs_to :products
  belongs_to :invoice
end

this fullfills following requirements:

Invoice and Product have a Many2Many relationship The relationship between an Invoice and a Product is a LineItem, which provides further information like price, amount, applied taxes, etc. You can create a LineItem by adding a Product:

invoice = Invoice.create
invoice.products << Product.find_by_name('awesome')

Your Invoice should only have line items! These can be a tree structure but you should not have products directly referenced from your invoice (what if a product price changes: this would affect existing invoices!)

So, to fix your structure:

invoice
  line_item   # references a product, but has its own fields (price!)
  line_item
    line_item

Each line_item should reference one product using belong_to. It's your join model between invoices and products:

class Invoice
  has_many :line_items
end

class LineItem
  belongs_to :invoice
  belongs_to :product
  acts_as_tree # (implies has_many :line_items with the parent invoice_id, etc.)
end

class Product
  has_many :line_items
end

This is basically all you need to build an invoice. You can think of the tree structure as being independent from the Invoice:LineItem:Product relationship. It can work as a flat list, or enhanced to become a tree.

If your products normally contain other products and you need to know which children to add to the invoice when the parent product is added (as line items), you'll need to tree your products too:

class Product
  has_many :line_items
  acts_as_tree
end

This tree structure is independent of the tree structure in line items. Remember: products can change, and this shouldn't affect existing line items in your invoices.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!