2

这是我的 before_save 方法:

  before_save :check_postal

  def check_postal
    first_three = self.postal_code[0..2]
    first_three.downcase!

    postal = Postal.find_by_postal_code(first_three)

    if postal
      self.zone_id = postal.zone_id
    else
      PostalError.create(postal_code: self.postal_code)
      return false
    end
  end

一切运行良好,self.zone_id = postal.zone_id但在else语句中,我PostalError.create(postal_code: self.postal_code)没有将记录保存到数据库中。

我知道这与return false声明有关,因为当我删除它时,它保存得很好——但这违背了目的..

如何PostalError在返回 false 以防止当前对象保存时获取要保存的新记录..

4

2 回答 2

4

你是对的:问题是before_save.

整个保存过程都包含在一个事务中。如果保存失败,无论是因为验证失败、回滚异常还是其他原因,事务都会回滚。这将撤消 PostalError 记录的创建。

通常这是一件好事 - 这样不完整的保存就不会留下碎屑

我可以想到两种方法来解决这个问题。一种是根本不在那里创建记录:一旦危险过去,使用after_rollback钩子执行它。

另一种方法是使用不同的数据库连接创建该记录(因为事务是每个连接的事物)。一个简单的方法是使用不同的线程:

Thread.new { PostalError.create(...)}.join

我坚持join在那里等待线程完成,而不是为您的应用程序添加您可能没想到的并发度。

于 2013-07-07T08:11:48.487 回答
-2

我不知道,但我试图猜测解决方案。

else
  PostalError.create(postal_code: self.postal_code)
  self.zone_id = postal.zone_id
end
于 2013-07-06T22:56:32.033 回答