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

Ruby on rails 我如何从我的控制器将这个复杂的事务重构到我的模型中?,ruby-on-rails,transactions,before-filter,Ruby On Rails,Transactions,Before Filter,我有一个复杂的保存过程(一个循环引用,需要通过验证和保存一个模型、验证和保存另一个模型,然后用第二个模型的id更新第一个模型来解决),该过程根据是否发生了不好的事情等进行回滚 我的模型是这样关联的: 帐户有一个站点联系人 账户s有许多客户s SiteContacts是客户的一种类型 客户s属于账户 由于周期性引用(即,客户没有帐户无效,但是帐户需要站点联系人,这是客户的一种类型),我决定先用一个空白id为站点联系人保存帐户,然后保存站点联系人 我有类似的代码: # remove the si

我有一个复杂的保存过程(一个循环引用,需要通过验证和保存一个模型、验证和保存另一个模型,然后用第二个模型的id更新第一个模型来解决),该过程根据是否发生了不好的事情等进行回滚

我的模型是这样关联的:

  • 帐户
    有一个
    站点联系人
  • 账户
    s有许多
    客户
    s
  • SiteContact
    s是
    客户的一种类型
  • 客户
    s属于
    账户
由于周期性引用(即,
客户
没有
帐户
无效,但是
帐户
需要
站点联系人
,这是
客户
的一种类型),我决定先用一个空白id为站点联系人保存帐户,然后保存站点联系人

我有类似的代码:

# 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
是否可以覆盖
帐户#save
或其他方法并将所有代码移动到我的控制器中?我在保存
之前查看了
,在创建
之前查看了
,但我担心可能会出现一些意外的递归,因为我必须保存
帐户
两次

有什么想法吗?

像这样的吗

控制器代码

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
型号代码

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
类帐户
在控制器中:

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
在您的
帐户中
型号

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
类帐户

保存将引发异常。这将自动回滚事务

这很复杂。我不做单表继承,所以有三个模型/表。帐户依赖于站点联系人,而站点联系人依赖于客户,客户依赖于帐户。实际上,这在关系数据库中并不是什么新鲜事,但它比在带有外键的模型中有一个
属于
,在另一个模型中有多个
/
有一个
更复杂。我没有读你问题的第二部分,所以忽略我回答中的PS,在回答中添加了额外的解释。