has_many:通过使用,简单,初学者的问题

时间:2011-09-23 05:13:07

标签: ruby-on-rails ruby-on-rails-3 activerecord

我正在编写一个简单的会计系统来管理成本。结构是这样的:

Invoice  - can have many products
  Product - can have many costs, also can act_as_tree 
      LineItem  - 
    Product
        LineItem
        LineItem
      Product
      LineItem
  Product
      LineItem
  LineItem

我将这个设置为三个类的has_many和belongs_to但是认为以下更合适(基于阅读Rails 3 Way - 任何缺点是我缺乏理解;只是尝试给出上下文)

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

 Class Product < ActiveRecord::Base
    belongs_to :invoice
    belongs_to :line_item
 end

class LineItem < ActiveRecord::Base
    has_many :products
    has_many :invoices, :through => :invoices
end

但我不这样做是正确的。

如果我执行以下操作:

>@i=Invoice.find(1)
>@i.products # this works
>@i.line_items # doesn't work, unidentified method line_items

这是我第一次使用has_many:through。这是否为我的数据模型设置正确?此外,是否可以将其与acts_as_tree结合使用 - 我希望能够说:

>@i.line_items 

并取回该特定发票的所有订单项。可能的?

请求帮助

3 个答案:

答案 0 :(得分:1)

首先提出一个问题:ProductLineItem之间的关系是什么:1个产品有多个订单项,或者是1和许多产品中引用的相同订单项?本答案的其余部分基于每个产品应该有多个订单项的假设。

我认为你的模型应该这样定义:

# 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

答案 1 :(得分:1)

你为什么选择这种结构?在这种情况下,我通常做

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

满足以下要求:

发票和产品具有Many2Many关系 发票和产品之间的关系是一个LineItem,它提供更多信息,如价格,金额,应用税等。 您可以通过添加Product:

来创建LineItem
invoice = Invoice.create
invoice.products << Product.find_by_name('awesome')

答案 2 :(得分:0)

您的发票只应包含订单项!这些可以是树形结构,但您不应该直接从发票中引用产品(如果产品价格发生变化,这会影响现有的发票!)

所以,要修复你的结构:

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

每个line_item都应使用belong_to引用一个产品。这是发票和产品之间的联合模式:

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

这基本上就是建立发票所需的全部内容。您可以将树结构视为独立于Invoice:LineItem:Product关系。它可以作为一个平面列表,或者增强成为一个树。

如果您的产品通常包含其他产品,并且您需要知道在添加父产品时将哪些子项添加到发票中(作为行项目),您还需要对产品进行树形化:

class Product
  has_many :line_items
  acts_as_tree
end

此树结构独立于订单项中的树结构。请记住:产品可能会发生变化,这不会影响发票中的现有订单项。