Транзакции в задаче Rake - PullRequest
       7

Транзакции в задаче Rake

2 голосов
/ 21 февраля 2011

Я пытаюсь создать грабли с поддержкой транзакций. Существует связь has_one между User-> Profile и User-> Location.

Следующий код должен завершиться сбоем, так как уже существует Пользователь с именем пользователя 'foo':

ActiveRecord::Base.transaction do

  begin

    u = User.create!(:username => 'foo', :email_address => 'foo@bar.com')

    p = Profile.create!(:first_name => 'foo', :last_name => 'bar')
    u.profile=p

    l = Location.create!(:address => "chanhassen,MN")
    u.location=l

  rescue Exception => e
    rollback()
    puts "error: #{e}"
  end

end # transaction

К сожалению, сообщение об ошибке (о повторяющейся записи) не возникает, и модели профиля и местоположения создаются, но не назначаются пользователю. Что я не понимаю?

- изменить -

Я использовал метод create! () Вместо метода create (). Это приводит к возникновению ошибки дублирующегося имени пользователя. Однако если проверка пользователя прошла успешно, но проверка профиля не удалась (например, поле last_name отсутствует), пользователь все еще создается в БД. Это должно вызвать сбой транзакции (это происходит) и откат пользователя (это не так).

Другой вопрос: User.create не генерирует идентификатор:

#<User id: nil, username: "foo">

в то время как Profile.create и Location.create делают:

#<Location id: 1, locatable_id: nil, locatable_type: nil>
#<Profile id: 1, user_id: nil, first_name: "foo", last_name: "bar">

Похоже, что все три модели должны ждать создания своего первичного ключа, пока все проверки не пройдут успешно. Это связано с отношением has_one?

Ответы [ 2 ]

2 голосов
/ 22 февраля 2011

Это имеет желаемое поведение:

ActiveRecord::Base.transaction do
  begin

    u = User.new(:username => 'foo', :email_address => 'foo@bar.com')

    l = Location.new(:address => "Chanhassen, MN")
    u.location=l

    p = Profile.new(:first_name => 'Foo', :last_name => 'Bar')
    u.profile=p

    u.save!

  rescue Exception => e
    ActiveRecord::Rollback
    puts e

  end
end # transaction

Метод new () (кажется) не запускает проверку.Метод save! () Делает.

2 голосов
/ 22 февраля 2011

Попробуйте использовать метод create! вместо create (как в User.create! :username => 'foo'). create не вызывает исключение при ошибке, create! делает это.

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