Save方法回滚并在有效时返回nil



Rails的save方法有问题;它似乎在该失败的时候失败了,但在该成功的时候却没有成功。

我有一个Claim模型,可以与任何Status一起保存,但如果要提交(status_id == 5),则必须接受条款和条件。

validates :terms_and_conditions, :acceptance => {:accept => true, :if => :submitted?}
def submitted? # simplified for this example
  status_id == 5
end

然而,我也存储了接受术语的时间(在db字段tnc_accepted_at下),并将terms_and_conditions定义为该字段的存在。(这一点很好,我只是不确定它是否与我的问题有关。)

def terms_and_conditions
  tnc_accepted_at.present?
end
def terms_and_conditions=(bool) # browser will pass '0' or '1'
  self.tnc_accepted_at = bool.in?([false, nil, 0, '', '0']) ? nil : DateTime.now
end

但问题是。索赔开始于以下状态:

claim
 => #<Claim id: 51, tnc_accepted_at: nil, status_id: 4>
claim.valid?
 => true

然后我尝试提交它:

claim.update_attributes! :status_id => 5
   (0.3ms)  BEGIN
  ClaimItem Load (1.5ms)  SELECT --blah blah blah
  Status Load (0.6ms)  SELECT --blah blah blah
   (0.4ms)  ROLLBACK
ActiveRecord::RecordInvalid: Validation failed: Terms and conditions must be accepted

这是完美的,但当我试图纠正错误时:

claim.update_attributes! :terms_and_conditions => true
   (0.3ms)  BEGIN
  ClaimItem Load (1.1ms)  SELECT --blah blah blah
   (0.7ms)  UPDATE "claims" --blah blah blah
   (0.2ms)  ROLLBACK
 => nil

这太奇怪了!我注意到,每当我试图保存记录时,无论在什么情况下(使用savesave!update_attributesupdate_attributes!:tnc_accepted_at => DateTime.now,这都无关紧要),我都会收到这个消息——如果有效,它会回滚并返回nil;如果无效,则会如您所期望的那样引发错误。

也许这个问题是针对老年人的?

我认为问题出在"new record"标志上(正如您所建议的)。如果保存了新记录,则"new record"设置为false,good,但如果存在回滚,则"new record"仍将具有值false,就像保存中的其他填充列将保持其值一样。如果尝试新的保存(使用正确的值),Rails中的save方法将执行数据库更新而不是数据库插入,因为"new record"为false。

我在一个非常旧的Rails版本中注意到了这一点,认为现在已经修复了。我在ActiveRecord::Base中用这个方法修复了它(Rails必须在内部使用@new_record才能工作)

def try_reset_new_record!
  if ! self.new_record? &&
      ( ! self.id || ! self.class.find_by_id(self.id) )
    @new_record = true
  end
end

ActiveRecord save方法返回nil的另一个原因是它被嘲笑。类似expect(modelInstance).to receive(:save) 的东西

当然,在我花了一整天的时间之后,这真的很简单…

因此,update_attributes似乎只能在已保存的记录上正常工作。

> claim
 => #<Claim id: 51, tnc_accepted_at: nil, status_id: 4>
> claim.valid?
 => true
#=========
> claim.save # This makes all the difference!
   (0.3ms)  BEGIN
  Claim Load (0.4ms)  SELECT --blah blah blah
   (1.0ms)  INSERT INTO "claims" --blah blah blah
   (14.8ms)  COMMIT
 => true
#=========
> claim.update_attributes! :status_id => 5
   (0.3ms)  BEGIN
  ClaimItem Load (1.5ms)  SELECT --blah blah blah
  Status Load (0.6ms)  SELECT --blah blah blah
   (0.4ms)  ROLLBACK
ActiveRecord::RecordInvalid: Validation failed: Terms and conditions must be accepted
# ... just as expected.
> claim.update_attributes! :terms_and_conditions => true
   (0.3ms)  BEGIN
  ClaimItem Load (0.8ms)  SELECT --blah blah blah
   (0.8ms)  UPDATE "claims" --blah blah blah
   (11.4ms)  COMMIT
 => true
# ... hooray!

最新更新