2012-09-24 77 views
2

假設一個模型會產生一個驗證錯誤,通常這是由控制器處理的,但是有可能由模型自動處理嗎?在Rails中,是否可以修復模型中的模型驗證錯誤?

實際上我想生成一個唯一的ID uid每個Note,模型看起來是這樣的:

class Note < ActiveRecord::Base 
    validates_uniqueness_of :uid 
    # ... some code to generate uid on after_initialize 
end 

我得到的最接近是:

class Note < ActiveRecord::Base 
    validates_uniqueness_of :uid 
    # ... some code to generate uid on after_initialize 

    after_rollback :repair 

    protected 

    def repair 
    if self.errors[:uid].size > 0 
     self.uid = generate_uid 
    end 
    self.save # Try again 
    end 
end 

一些眼前的問題與我的解決方案: (1)模型實例仍然存在控制器可以看到的錯誤,我不知道如何清除錯誤。 (2)修復方法是遞歸的。

+2

我不會這樣。在過濾器或驗證之前/之後重新保存模型是解決問題的絕佳方法。 –

+0

@ErezRabih是正確的,除了使用真正的uuid生成器,我想我會創建一個像''''save_with_repair'''這樣的附加方法,如果安全失敗並且具有唯一的約束,那麼它會重試。 – phoet

回答

0

我會使用一個真實的UUID,它保證是唯一的,而不會將開銷添加到您的模型中。在模型中進行唯一性驗證會增加一些開銷,因爲它必須擊中數據庫才能確定是否存在某些內容,而且它甚至不能保證。

看看這個Ruby項目產生的UUID:https://github.com/assaf/uuid/

2

雖然我敢肯定有一種方法在模型(也許after_validation回調可能是使用的)來捕捉和處理錯誤,也許你可以通過確保在創建時生成的uid是唯一的,避免此問題。

Ryan Bates offered this method for generating unique tokens in a RailsCast

def generate_token(column) 
    begin 
    self[column] = SecureRandom.urlsafe_base64 
    end while User.exists?(column => self[column]) 
end 

與使用before_create回調,即before_create { generate_token(:uid) },每個型號都會有一個唯一的ID。

所有這一切說,@Beerlington提出了關於UUID的一個非常好的觀點。

更新:請注意,該方法預計將在User模型中定義。對於你的例子,你想要將它改爲...while Note.exists?...