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

时间:2012-08-28 23:11:01

标签: ruby-on-rails-3.1

我遇到了Rails'save方法的问题;它似乎应该失败,但应该在它应该成功时失败。

我有Claim模型,可以使用任何Status保存,但如果要提交(status_id == 5)则必须接受条款和条件。< / p>

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;如果无效,则会出现错误。

3 个答案:

答案 0 :(得分:2)

也许这个问题是旧的?

我认为问题是"new record"标志(正如您所建议的那样)。如果保存了新记录,则"new record"设置为false,但是如果存在回滚,则"new record"仍将具有值false,就像保存中的其他已填充列将保持为值。 如果尝试了新的保存(使用正确的值),Rails中的save方法将执行db-update而不是db-insert,因为"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

答案 1 :(得分:0)

当我花了一整天的时间之后,它自然而然地非常简单......

所以似乎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!

答案 2 :(得分:0)

ActiveRecord save方法返回nil的另一个原因是它是否被模拟。像expect(modelInstance).to receive(:save)

这样的东西