我遇到了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
......这很奇怪!而且我注意到,无论在什么情况下(使用save
,save!
,update_attributes
,update_attributes!
,我都会在尝试保存记录时得到此信息, :tnc_accepted_at => DateTime.now
,没关系) - 如果有效,它会回滚并返回nil;如果无效,则会出现错误。
答案 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)