我有下面的代碼塊:ActiveRecord的異常不及時搶救
unless User.exist?(...)
begin
user = User.new(...)
# Set more attributes of user
user.save!
rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotUnique => e
# Check if that user was created in the meantime
user = User.exists?(...)
raise e if user.nil?
end
end
的原因是,因爲你可能已經猜到了,多個進程會調用此方法的同時創建用戶(如果它不已經存在),所以當第一個進入塊並開始初始化新用戶,設置屬性並最終調用save!時,用戶可能已經被創建。 在這種情況下,我想再次檢查用戶是否存在,並且只在異常時纔會引發異常(=如果沒有其他進程在此期間創建它)。
問題是,定期從保存提出ActiveRecord :: RecordInvalid異常!並沒有從營救區域救出。 任何想法?
編輯:
好吧,這很奇怪。我肯定錯過了什麼。我根據Simone的提示,看起來像這樣重構代碼:
unless User.find_by_email(...).present?
# Here we know the user does not exist yet
user = User.new(...)
# Set more attributes of user
unless user.save
# User could not be saved for some reason, maybe created by another request?
raise StandardError, "Could not create user for order #{self.id}." unless User.exists?(:email => ...)
end
end
現在,我得到以下異常:
ActiveRecord::RecordNotUnique: Mysql::DupEntry: Duplicate entry '[email protected]' for key 'index_users_on_email': INSERT INTO `users` ...
在那裏說:「除非user.save」行拋出。 這怎麼可能? Rails認爲可以創建用戶,因爲電子郵件是唯一的,但是Mysql唯一索引阻止插入?那有多可能?怎樣才能避免?
感謝您的回答,Simone!我使用Devise進行身份驗證,因此User模型包含唯一性驗證,並且電子郵件上有唯一索引。我可以重構我的代碼 開始 user.save! 救援... 結束 到 如果user.save 其他 ... 結束 但我更感興趣的是我原來的問題:爲什麼是我原來沒有捕獲的ActiveRecord :: RecordInvalid例外碼? – 2011-01-07 15:51:04