使用accepts_nested_attributes_for
. 但答案只是说这很难,如果不是不可能的话!. accepts_nested_attributes_for
是一种有点复杂的方法,但它有效 - 除非您尝试基于子模型的计算来验证模型。我可能已经找到了解决计算问题的方法。
我正在开发一个基于网络的复式记账应用程序,它具有以下基本模型;
class Account < ApplicationRecord
has_many :splits
has_many :entries, through: :splits
end
class Entry < ApplicationRecord
has_many :splits, -> {order(:account_id)}, dependent: :destroy, inverse_of: :entry
validate :balanced?
end
class Split < ApplicationRecord
belongs_to :entry, inverse_of: :splits
belongs_to :account
validates_associated :account
validates_associated :entry
end
条目(交易)必须至少有两个拆分,拆分中的金额属性(或借方/贷方)之和必须等于 0。我虽然validate :balanced?
会处理它,但明显的 Javascript 错误允许输入不平衡。我还没有找到错误,但由于条目不平衡,我无法更新它,因为valid?
在我尝试添加的新拆分上不起作用(返回 false)。
分类帐accepts_nested_attributes_for
表单已经退出了一些不应允许提交不平衡交易的 Javascript。均衡?创建时未设置错误,但更新时出现错误。我修复它的方法不是使用不起作用的验证,而是依赖与以下方法一起调用的方法@entry.update(entry_params)
:
class Entry < ApplicationRecord
has_many :splits, -> {order(:account_id)}, dependent: :destroy, inverse_of: :entry
# validate :balanced? # took this out since its after the fact, balanced? method can still be called
accepts_nested_attributes_for :splits,
:reject_if => proc { |att| att[:amount].to_i.zero? && att['account_id'].to_i.zero?},
allow_destroy: true
def valid_params?(params)
split_sum = 0
params_hash = params.to_h
params_hash[:splits_attributes].each{|k,s| split_sum += s[:amount].to_i if s[:_destroy].to_i.zero?}
unless split_sum.zero?
errors.add(:amount, "Unbalanced: debits, credits must balance")
return false
else
return true
end
end
end
end
# update action from Entry Controller
def update
respond_to do |format|
if @entry.valid_params?(entry_params) && @entry.update(entry_params)
format.html { redirect_to account_path(session[:current_acct]), notice: 'Entry was successfully updated.' }
format.json { render :show, status: :ok, location: @entry }
else
# ... errr
end
end
end
同样,这只不过是验证参数与不适用于这种情况的模型验证。
这可能与答案 2 大致相同,但不使用回调,只是调用控制器