Как транзакции могут быть использованы в Ruby DataMapper? - PullRequest
2 голосов
/ 16 сентября 2011

У меня есть класс, который выполняет операторы SQL (обновления, вставки и удаления), которые хранятся в файле YAML.Я хотел бы, чтобы все заявления были частью одной транзакции.Если какой-либо из операторов SQL потерпит неудачу, он будет откатан.Если все утверждения успешны, то они будут зафиксированы.Я подключаюсь к базе данных MySQL.Вот мой код:

require 'dm-core'

class SqlExecuter

  def initialize(input_yaml_file_name)
    @input_yaml_file_name = input_yaml_file_name
    @adapter = DataMapper.repository(:default).adapter
    @sql_statements = YAML::load(File.open(input_yaml_file_name))
  end

  def execute()
    puts "Executing SQL statements in #{@input_yaml_file_name} file...."

    @sql_statements.each do | sql_statement |
      @adapter.execute(sql_statement)
    end
  end
end # class SqlExecuter

Я бы хотел, чтобы все мои вызовы @ adapter.execute были частью одной транзакции.Я посмотрел код в геме dm-Transactions, но не могу понять, как его использовать в этом контексте.

Ответы [ 3 ]

5 голосов
/ 16 сентября 2011

Используйте это для включения операторов SQL в транзакцию и отката при возникновении ошибки:

require 'dm-transactions'
YourModel.transaction do |t|
  begin
    @sql_statements.each do |sql_statement|
      DataMapper.repository(:default).adapter.execute(sql_statement)
    end
  rescue DataObjects::Error
    t.rollback
  end
end

Посмотрите на Использование транзакций с Ruby DataMapper и dm-transactions_spec.rb

4 голосов
/ 25 апреля 2012

Насколько я могу судить, вам больше не нужно звонить rollback() для отката транзакции.Вам просто нужно заключить его в блок транзакции, например так:

YourModel.transaction do
  @sql_statements.each do |sql_statement|
    DataMapper.repository(:default).adapter.execute(sql_statement)
  end
end

По крайней мере, так я прочитал спецификацию dm-транзакций об откатах :

it 'should rollback when an error is raised in a transaction' do
  @user_model.all.size.should == 0
  lambda {
    @user_model.transaction do
      @user_model.create(:name => 'carllerche')
      raise 'I love coffee'
    end
  }.should raise_error('I love coffee')
  @user_model.all.size.should == 0
end

Я писал значительное приложение, использующее DataMapper с большим количеством транзакций и без использования rollback(), и все мои неудачные транзакции всегда откатывались.

Кроме того, из того, что я помню об ActiveRecord (Прошел год с тех пор, как я использовал AR), поведение транзакции DataMapper имитирует поведение AR.

0 голосов
/ 16 сентября 2011

Im принцип, ответ по-прежнему правильный User.transaction откроет транзакцию в репозитории (базе данных), к которой присоединена модель «Пользователь». Более общий способ -

DataMapper.repository(:default).transaction do |t|
    t.commit
end
...