Как получить семантику сохранения (без восклицательного знака) в транзакции ActiveRecord? - PullRequest
3 голосов
/ 20 марта 2010

У меня есть две модели: Person и Address, которые я хотел бы создать в транзакции. То есть я хочу попытаться создать Person и, если это удастся, создать связанный Address. Я хотел бы использовать семантику save (возврат true или false), а не семантику save! (повысить ActiveRecord::StatementInvalid или нет).

Это не работает, потому что user.save не вызывает откат транзакции:

class Person
  def save_with_address(address_options = {})
    transaction do
      self.save
      address = Address.build(address_options)
      address.person = self
      address.save
    end
  end
end

(Изменение вызова self.save на блок if self.save вокруг остальных не помогает, потому что сохранение Person все еще успешно, даже когда сбой Address.)

И это не работает, потому что оно вызывает исключение ActiveRecord::StatementInvalid из блока transaction без запуска ActiveRecord::Rollback:

class Person
  def save_with_address(address_options = {})
    transaction do
      save!
      address = Address.build(address_options)
      address.person = self
      address.save!
    end
  end
end

Документация Rails специально предупреждает о перехвате ActiveRecord::StatementInvalid внутри блока transaction.

Полагаю, мой первый вопрос: почему этот блок транзакций ... не обрабатывает оба сейва?

Ответы [ 2 ]

5 голосов
/ 20 марта 2010

Как насчет этого?

class Person
  def save_with_address(address_options = {})
    tx_error = false
    transaction do
      begin
        self.save!
        address = Address.build(address_options)
        address.person = self
        address.save!
      rescue Exception => e
        # add relevant error message to self using errors.add_to_base
        raise ActiveRecord::Rollback 
        tx_error = true 
      end
    end
    return true unless tx_error

    # now roll back the Person TX.
    raise ActiveRecord::Rollback
    return false
  end
end

Мне не нравится способ реализации TX. Но именно так вы можете обойти проблемы.

0 голосов
/ 20 марта 2010

Скажите ActiveRecord, чтобы сделать это для вас. Избавляет вас от проблем:

class Person < ActiveRecord::Base
  belongs_to :address, :autosave => true
end

Приятно, что ошибки Person будут содержать ошибки проверки адреса, правильно отформатированные.

См. Модуль AutosaveAssocation для получения дополнительной информации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...