我有模特:
Transaction has_many :credits, :debits
Credit belongs_to :transaction
Debit belongs_to :transaction
每个信用证必须有平衡借记,反之亦然。
我目前(成功)使用以下内部事务的create方法实现此目的:
@transaction = Transaction.new(params[:transaction])
Transaction.transaction do
# Balance debits with credits (Sales)
if params[:balance_transaction] == 'credit'
@transaction.credits.each do |credit|
@transaction.debits.push(Debit.new({
:quantity => 0,
:cost_per_unit => 0,
:description => 'Balancing Debit',
:amount => credit.amount,
:account_id => 23 #Get from settings in future to allow users to choose Debtor account
}))
end
elsif params[:balance_transaction] == 'debit'
@transaction.debits.each do |debit|
@transaction.credits.push(Credit.new({
:quantity => 0,
:cost_per_unit => 0,
:description => 'Balancing Credit',
:amount => credit.amount,
:account_id => 43 #Get from settings in future to allow users to choose Creditor account
}))
end
else
raise ActiveRecord::Rollback # There's no balancing transaction. Don't save it!
end
end
我尝试通过替换@transactions.credits.push(...) with debit.balancing_credit
并将以下内容放入借记模型中,将平衡借记/贷记创建转移到借记/贷记模型中:
def balancing_credit
transaction.credits.new({
:quantity => 0,
:cost_per_unit => 0,
:description => 'Balancing Debit',
:amount => amount,
:account_id => 43 #Get from settings in future to allow users to choose Creditor account
})
end
我认为这是非常简单的重构,但它会引发undefined method 'debits' for nil:NilClass
错误。似乎它在数据库中查找尚未保存的交易以创建平衡信用额度?我做错了吗?
答案 0 :(得分:1)
你是对的,这样的机制应该属于模型,而不属于控制器。您可以在Transaction模型上进行before_save回调:
class Transaction
after_save :balance_operations
def balance_operations
if credits
credits.each do|credit|
debit = debits.build (#do all your stuff here. build() automaticly fills the transaction_id field of your new debit with the proper id)
return false unless debit.save
end
if debits # can use elsif if mutually exclusive conditions
# same thing as above
end
end
end
这依赖于回调链包装在ActiveRecord :: Base.transaction中的事实。如果回调返回false,则ActiveRecord将执行回滚。有关详细信息,请参阅“交易”一章 here 。
如果您在一个交易中有许多操作,您还可以查看a look at this to improve performance。
修改:您还可以将validates_associated :debit, :credits
添加到模型中