我有一个复杂的保存过程(一个循环引用,需要通过验证和保存一个模型来解决,验证并保存另一个模型,然后用第二个id更新第一个)具有回滚,具体取决于是否有什么不好发生了等等。
我的模型以这种方式相关:
Account
有一个SiteContact
。Account
有很多Customer
s。SiteContact
是一种Customer
。Customer
属于Account
由于周期性参考(即Customer
s无效而没有Account
,但Account
需要SiteContact
这是Customer
的类型。 )我决定使用空白ID为帐户保存首先,然后保存site_contact。
我的代码类似于:
# remove the site contact from the account because its not valid yet.
site_contact = params[:account].delete(:site_contact_attributes)
account = Account.new(params[:account])
# some pseudo code
# start database transaction
# validate account
# if valid then
# save account
# site_contact.account_id = account.id
# validate site_contact
# if valid then
# account.site_contact_id = site_contact.id
# save account
# break out!
#
# else
# rollback transaction
# end
# else
# rollback transaction
# end
if Account.exists?(account)
# everything was good! flash[:notice] and redirect somewhere
else
# something bad happened, go back to the page and display the errors.
end
是否可以覆盖Account#save
或其他一些方法并将所有代码移动到我的控制器中?我看着before_save
和before_create
,但我担心可能会有一些意外的递归,因为我必须保存account
两次。
有什么想法吗?
答案 0 :(得分:2)
在您的控制器中:
site_contact = SiteContact.new(params[:account].delete(:site_contact_attributes))
account = Account.new(params[:account])
if account.save_nested(site_contact)
# success
else
# error
end
在Account
模型中。
class Account < ActiveRecord::Base
def save_nested(site_contact)
Account.transaction do
save!
site_contact.account_id = self.id
site_contact.save!
self.site_contact_id = site_contact.id
save!
return true
end
return false
end
end
验证失败时,save!
将抛出异常。这将自动回滚事务。
答案 1 :(得分:0)
这样的东西?
控制器代码
site_contact = params[:account].delete(:site_contact_attributes)
account = Account.new(params[:account])
if Account.validate_and_save(site_contact)
# everything was good! flash[:notice] and redirect somewhere
else
# something bad happened, go back to the page and display the errors.
end
型号代码
class Account < ActiveRecord::Base
def validate_and_save(site_contact)
# some pseudo code
# start database transaction
# validate account
# if valid then
# save account
# site_contact.account_id = account.id
# validate site_contact
# if valid then
# account.site_contact_id = site_contact.id
# save account
# break out!
# return true
# else
# rollback transaction
# return false
# end
# else
# rollback transaction
# return false
# end
end
end