Я пытаюсь создать грабли с поддержкой транзакций. Существует связь 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?