Обернуть все действия контроллера в транзакциях в Rails - PullRequest
9 голосов
/ 14 декабря 2011

Можно ли настроить приложение Rails таким образом, чтобы все действия контроллера автоматически переносились с транзакцией, которая автоматически откатывается в случае неотключенных исключений?

Я работаю над приложением Rails 3, в настоящее время над довольно сложным действием, которое вносит многочисленные изменения в базу данных. И я много раз ошибался! Через некоторое время я понял, что мой код не работает, потому что в результате я получил противоречивые данные в базе данных.

Я могу достаточно легко обернуть это транзакцией (это очевидный случай, когда она необходима!). Однако это заставило меня задуматься о том, что, по крайней мере, в процессе разработки было бы полезно применить эту идею для каждого действия контроллера.

Если это возможно, есть ли у этого недостаток?

Ответы [ 2 ]

17 голосов
/ 15 декабря 2011

Для информации, я сделал это с помощью round_filter в контроллере приложения:

around_filter :wrap_in_transaction

def wrap_in_transaction
  ActiveRecord::Base.transaction do
    yield
  end
end

Это просто откатывает транзакцию для любого необработанного исключения и повторно вызывает исключение.

5 голосов
/ 14 декабря 2011

Можно ли это сделать?наверное.Это должно быть сделано?вероятно, нет, иначе это было бы частью рельсов, или для этого уже была бы большая жемчужина.

Если у вас есть определенные сложные действия контроллера, которые выполняют много операций с БД, и вы хотите, чтобы они были в транзакции, я советую перенести эту бизнес-логику и постоянство в метод модели и поместить вашу транзакциютам.Это также дает вам больше контроля в тех случаях, когда вы не всегда хотите, чтобы это произошло.

Если вы действительно, действительно хотите сделать это в любом случае, я бы поспорил, что вы могли бы сделать это с промежуточным программным обеспечением Rack, как это (непроверенный) один https://gist.github.com/1477287:

# make this class in lib/transactional_requests.rb, and load it on start
require 'activerecord'

class TransactionalRequests
  def initialize(app)
    @app = app
  end

  def call(env)
    ActiveRecord::Base.transaction do
      @app.call(env)
    end
  end
end

# and in the app config
config.middleware.use "TransactionalRequest"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...