4

我正在编写一个 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(这个循环在另一个循环遍历项目的循环内,这是“项目”变量的来源)。以及我从这些页面中获得的所有相关项目。

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

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

4

1 回答 1

15

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

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

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

值得注意的是,您也可以使用类似的东西ItemRelation.transaction,但事务不是特定于模型的,所以它的工作原理是一样的。

更多信息可以在Active Record 交易页面上找到。

收到 Ctrl+C 后,没有办法等待和完成某些事情;基于事务的方法是要走的路。

于 2012-04-28T23:23:24.590 回答