Clients
有很多Invoices
。发票具有number
属性,我想通过递增客户的先前发票编号来初始化该属性。
例如:
@client = Client.find(1)
@client.last_invoice_number
> 14
@invoice = @client.invoices.build
@invoice.number
> 15
我希望将此功能添加到我的Invoice
模型中,但我不确定如何操作。这就是我想象的代码:
class Invoice < ActiveRecord::Base
...
def initialize(attributes = {})
client = Client.find(attributes[:client_id])
attributes[:number] = client.last_invoice_number + 1
client.update_attributes(:last_invoice_number => client.last_invoice_number + 1)
end
end
但是,当我致电attributes[:client_id]
时,@client.invoices.build
未设置。
如何以及何时初始化发票client_id
,以及何时可以使用它来初始化发票number
?我可以将这个逻辑放入模型中,还是必须将它放在控制器中?
答案 0 :(得分:7)
生成向用户表添加invoices_number
列的迁移。然后在Invoice
模型中写下这个:
class Invoice < ActiveRecord::Base
belongs_to :user, :counter_cache => true
...
end
创建发票后,这将自动为用户增加invoices_count
属性。
答案 1 :(得分:5)
怎么样:
class Invoice < ActiveRecord::Base
...
def initialize(attributes = {})
super
self.number = self.client.invoices.size + 1 unless self.client.nil?
end
end
答案 2 :(得分:1)
首先,您不需要使用属性集合,只需执行self.client_id
即可。更好的是,只要您的belongs_to :client
中有Invoice
,就可以self.client.last_invoice_number
。最后,如果更新或创建失败,您几乎总是想要引发异常,因此习惯使用update_attributes!
,这是一个更好的默认选择。 (如果您对这些要点有任何疑问,请询问,我会详细介绍)
现在已经不在了,你遇到了一些使用ActiveRecord的问题,初始化方法几乎永远不是正确的选择。 AR为您提供了一系列方法,可以连接到您需要的生命周期的任何一点。这些是
after_create
after_destroy
after_save
after_update
after_validation
after_validation_on_create
after_validation_on_update
before_create
before_destroy
before_save
before_update
before_validation
before_validation_on_create
before_validation_on_update
你可能想要的是挂钩到before_create。像这样的东西
def before_create
self.number ||= self.client.last_invoice_number + 1 unless self.client
end
它会做什么,它将为您的客户端启动数据库,获取最后一个发票号,将其递增1,并将其设置为新号码,但前提是您尚未设置号码(| | =将分配,但仅在左侧为零的情况下,并且仅当您在保存之前设置了客户端(或client_id)时才会分配。
答案 3 :(得分:1)
根据Jonathan R. Wallace的评论,以下是关于after_initialize
的一些有用的讨论:
http://blog.dalethatcher.com/2008/03/rails-dont-override-initialize-on.html