Rails将两个不同的模型实例保存为单个事务

时间:2016-05-25 12:18:53

标签: mysql ruby-on-rails ruby

我正在为一个注册表单编写一个服务对象,该表单记录用户和公司模型的数据(仅供参考,我拒绝使用nested_attributes)。

如果没有公司(belongs_to),用户就不能存在。

IF 公司成功且用户未能成功保存,如何回滚公司的创建?

我在下面复制了测试以证明这一点..

  context 'when both are valid?' do
    subject { -> { sign_up_object.save } }
    it { should change(Company, :count).by(1) }
    it { should change(sign_up_object, :company).to be_a Company }
    it { should change(User, :count).by(1) }
    it { should change(sign_up_object, :user).to be_a User }
  end
  context 'when COMPANY is invalid' do
    subject { -> { sign_up_object.save } }
    before { allow_any_instance_of(Company).to receive(:save!).and_return false }
    it { should change(User, :count).by(0) }
    it { should change(Company, :count).by(0) }
  end
  context 'when USER is invalid' do
    before { allow_any_instance_of(User).to receive(:save!).and_return false }
    subject { -> { sign_up_object.save } }
    it { should change(User, :count).by(0) }
    it { should change(Company, :count).by(0) }  ->>>> this one fails!!!
  end

我目前的代码看起来像这样

class SignUp

  ......

  def save_resources
    ActiveRecord::Base.transaction do
      save_company
      save_user
    end
  end

  def save_company
    company = new_company
    self.company = company if company.save!
  end

  def save_user
    user = new_user
    self.user = user if user.save!
  end
end

我确定ActiveRecord::Base.transaction区块实际上并没有做任何事情,因为我的测试显示用户规格是唯一失败的,因为公司数量增加了1. / p>

2 个答案:

答案 0 :(得分:1)

您可以在未创建用户时手动回滚事务:

举起你的榜样:

class SignUp

  ......

  def save_resources
    ActiveRecord::Base.transaction do
      save_company
      save_user
      raise ActiveRecord::Rollback if self.user.nil?
    end
  end

  def save_company
    company = new_company
    self.company = company if company.save!
  end

  def save_user
   user = new_user
   self.user = user if user.save!
 end
end

答案 1 :(得分:0)

如果user.save是unuccsessful

,你可以摧毁公司
def save_resources    
  company = save_company
  user = save_user
  company.destroy if user.nil?
end