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
这太奇怪了!我注意到,每当我试图保存记录时,无论在什么情况下(使用save
、save!
、update_attributes
、update_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!