如何使用多个Rails保存方法创建事务?

时间:2017-07-28 21:08:31

标签: ruby-on-rails model transactions ruby-on-rails-5

我正在使用Rails 5.我有一个看起来像这样的模型

class CryptoIndexCurrency < ApplicationRecord
  belongs_to :crypto_currency
end

我有一个服务方法,我希望用记录填充此表,我喜欢这样做

CryptoIndexCurrency.delete_all
currencies.each do |currency|
  cindex_currency = CryptoIndexCurrency.new({:crypto_currency => currency})
  cindex_currency.save
end

问题是以上不是非常交易的,只要在第一个语句之后发生了某些事情,&#34; delete_all&#34;将会执行,但没有其他任何东西。在这里创建事务的正确方法是什么,同样重要的是,我在哪里放置代码?想在这里了解Rails惯例。

2 个答案:

答案 0 :(得分:0)

我认为你可以做到:

CryptoIndexCurrency.transaction do
  CryptoIndexCurrency.delete_all
  CryptoIndexCurrency.create(currencies.map{ |c| {crypto_currency: c} })
end

答案 1 :(得分:0)

如果您使用的是Activerecord,则可以使用内置事务处理机制。否则,一种方法是确保验证所有数据,并且只在一切有效时保存。看看validates_associate之类的。

也就是说,如果您的流程本质上是无法验证/不确定的(例如,您调用外部API来验证付款),那么最好是确保您有一些清理方法来处理您的失败

如果您有确定性的失败:

def new_currencies_valid?(currencies)
  currencies.each do 
    return false if not currency.valid?(:create)
  end
  true
end

if new_currencies_valid?(new_currencies)
  Currency.delete_all # See note
  new_currencies.each(&:save)
end

旁注:除非你真的明白你在做什么,否则我建议调用destroy_all在删除时运行回调(例如删除dependent: :destroy)关联