如何从控制器中将这个复杂的事务重构到我的模型中?

时间:2010-11-09 22:30:18

标签: ruby-on-rails transactions before-filter

我有一个复杂的保存过程(一个循环引用,需要通过验证和保存一个模型来解决,验证并保存另一个模型,然后用第二个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_savebefore_create,但我担心可能会有一些意外的递归,因为我必须保存account两次。

有什么想法吗?

2 个答案:

答案 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
相关问题