简体   繁体   English

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

[英]How do I use an ActiveRecord Transaction in a Rake Task to rollback in the case of a Ctrl+C interrupt

I'm writing a rake task that creates records in my database and can run for an indefinite amount of time. 我正在写一个rake任务,它在我的数据库中创建记录,并且可以无限期地运行。 one aspect of the task is creating many-to-many associations between models. 该任务的一个方面是在模型之间创建多对多关联。 If I were to quit the task while it's adding entries to a join table it wouldn't finish relating that model. 如果我在向连接表添加条目时退出任务,则无法完成与该模型的关联。 here's some code from the task: 这是来自任务的一些代码:

(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

Here I'm iterating over all the pages of related items and creating an ItemRelation between the current item (this loop is inside another loop that loops over items, this is where the 'item' variable is from). 在这里,我迭代相关项的所有页面,并在当前项之间创建一个ItemRelation(此循环位于循环项目的另一个循环内,这是'item'变量来自的位置)。 and all the related items I get from scraping these pages. 以及从抓取这些页面得到的所有相关项目。

If I were to exit the program while iterating over these pages the current item would not be completed related and the stage wouldn't be updated at the end. 如果我在迭代这些页面时退出程序,则当前项目将无法完成相关,并且该阶段不会在最后更新。

So how can I wrap all this in a transaction that will rollback when I do Ctrl+C, or it will finish the loop, update the stage, and then exit instead of going to the next item to relate 那么如何在我执行Ctrl + C时将所有这些包装在将回滚的事务中,或者它将完成循环,更新阶段,然后退出而不是转到下一个要关联的项目

You can wrap things within a transaction using a transaction block. 您可以使用transaction块将事物包装在transaction As an example: 举个例子:

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

If the end is not reached, then SQL COMMIT will not be applied, meaning that none of the relations above will be created. 如果未到达end ,则不会应用SQL COMMIT ,这意味着不会创建上述任何关系。

It's worth noting that you can use something like ItemRelation.transaction , too, but transactions are not model-specific, so it works out the same. 值得注意的是,您也可以使用像ItemRelation.transaction这样的东西,但事务不是特定于模型的,所以它的工作原理相同。

More information can be found on the Active Record Transactions page. 可以在“ Active Record Transactions”页面上找到更多信息。

There's no way of waiting and finishing something off after receiving Ctrl+C; 收到Ctrl + C后,无法等待并完成某些操作; a transaction-based approach is the way to go. 基于交易的方法是可行的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM