如何使用PG Ruby Gem有条件地回滚事务

时间:2013-11-18 15:49:04

标签: ruby postgresql transactions pg

我目前正在学习数据库课程,其中一个实验室问题让我难以理解如何实现上述内容,实际上,如果有可能的话。我试过搜索docs但是定义的事务方法非常模糊。

这是我第一次尝试进行任何数据库操作而没有Rails的舒适毯,所以我有点迷失。我已经设法创建了一个与postgresql数据库的连接并且可以执行语句,我需要做的最后一件事就是根据一个简单的条件回滚一个事务。

请允许我向您展示代码:

require 'pg'
@conn = PG::Connection.open(:dbname => 'db_15_11_labs')
@conn.prepare('insert', 'INSERT INTO house (housenumber, street) VALUES ($1, $2) returning id')
@words = ["Foo", "Bar", "Bash", "Bang"]

def populate
  100.times.each_with_index do |i|
    # cycle through the @words array for street names, use i as house number
    ins = @conn.exec_prepared('insert', [i, "#{@words1[i % 4]} street"])
  end
end

基本上,条件是如果返回的id(ins[0]['id'])是偶数,则回滚事务。我认为如果ins[0]['id'] % 2 == 0我需要抛出某种异常但我该怎么做,更重要的是,如何将这些信息编码为docs中给出的语法?

感谢您的时间。

编辑1

我现在设法获得了允许条件放在已定义事务中的语法,如下所示:

@conn.transaction do |conn|
    ins = @conn.exec_prepared('insert', [i, "#{@words1[i % 100]} street"])
end

所以这个问题真的变得越来越多"我如何在ins[0]['id'] % 2 == 0

时抛出并捕获异常

我尝试过几个关于提高异常的简单教程,但执行以下操作:

throw :id_exception if (@ins[0]['id'].to_i % 2) == 0
    catch :id_exception do
    puts "caught :id_exception #{}"
end
交易中的

会产生'throw': uncaught throw :id_exception (ArgumentError)

2 个答案:

答案 0 :(得分:3)

如果在块内引发异常,则会自动回滚事务。所以你只需要为自己创建一个Exception类,在块中引发一个,然后安排拯救它,这样你的程序就不会因为引发异常而退出错误。

尝试这样的事情:

class MyLittleIdError < StandardError
end

begin
    @conn.transaction do |conn|
        ins = conn.exec_prepared('insert', [i, "#{@words1[i % 100]} street"])
        raise MyLittleIdError if (ins[0]['id'].to_i % 2) == 0
    end
rescue MyLittleIdError
    puts "aha! we should have rolled back."
end

答案 1 :(得分:-1)

您可以尝试将insert语句包装在ActiveRecord::Base.transaction中,然后在执行插入操作后,检查ins[0]['id']的值,如果它是偶数,则抛出一个回滚异常...查看{{ 3}} ActiveRecord::Base.transaction

我唯一担心的是我不确定这会与exec_prepared一起使用 - 我猜测它会,但是值得测试以确认这一点。