在Ctrl + C中断的情况下,如何在Rake任务中使用ActiveRecord事务进行回滚

时间:2012-04-28 17:23:56

标签: ruby-on-rails activerecord transactions rake interrupt

我正在编写一个rake任务,它在我的数据库中创建记录,并且可以无限期地运行。该任务的一个方面是在模型之间创建多对多关联。如果我在向连接表添加条目时退出任务,则无法完成与该模型的关联。这是来自任务的一些代码:

(1..100).each do |page|

    related = Nokogiri::HTML(open(url + "item/#{item.id}/related/#{page}"))

    related.css('.box').each do |box|
      id = box.css('a').first.attr(:href).scan(/\/(\d+)\//)[0][0].to_i
      title = box.css('p.title a').text
      related_item = Item.create :title => title, :foreign_id => id
      ItemRelation.create :item => item, :related_item => related_item
    end

end

item.update_attributes :stage => ItemStage::RELATED

这里我迭代相关项的所有页面并在当前项之间创建一个ItemRelation(此循环位于另一个循环项目的循环内,这是'item'变量来自的位置)。以及我从抓取这些页面得到的所有相关项目。

如果我在迭代这些页面时退出程序,则当前项目将无法完成相关,并且最后阶段不会更新。

那么如何在我执行Ctrl + C时将所有这些包装在一个将回滚的事务中,或者它将完成循环,更新阶段,然后退出而不是转到下一个要关联的项目

1 个答案:

答案 0 :(得分:14)

您可以使用transaction块在事务中包装内容。举个例子:

ActiveRecord::Base.transaction do
    # create relation 1
    # create relation 2
    # Ctrl+C
    # create relation 3
end

如果未达到end,则不会应用SQL COMMIT,这意味着不会创建上述任何关系。

值得注意的是,您也可以使用类似ItemRelation.transaction的内容,但事务不是特定于模型的,因此它的工作原理相同。

可以在Active Record Transactions页面找到更多信息。

收到Ctrl + C后,无法等待和完成某些事情;基于交易的方法是可行的方法。