2013-07-19 20 views
0

我有一個ActiveRecord mixin(我認爲您可以稱之爲?),它爲這些模型添加了各種默認範圍和回調,用於範圍多租戶查詢。使用mixin修改ActiveRecord驗證

我還希望能夠做的是修改該模型的現有唯一性驗證以包含範圍。我發現我可以看到使用Model.validators所有的驗證,所以我很自然地試圖修改範圍選項,如下所示:

Model.validators 
    .select{|v| v.is_a?(ActiveRecord::Validations::UniquenessValidator)} 
    .map{|v| v.options[:scope] = :client_id } 

..然而,這導致錯誤RuntimeError: can't modify frozen Hash,爲options哈希值。任何人都知道我可以怎麼做呢?我知道它可能會涉及一些漂亮的hacky代碼。

如果編輯它是不可能的,也許我可以覆蓋它或抓住它或什麼?

編輯 - 我找到了this,這幾乎正是我想要做的,但它不會在Rails 3.2中工作,我認爲他們完全改變了驗證的存儲方式。任何人都可以幫助我/給我指出如何讓這個工作在Rails 3中?

+0

確實有一個原因,爲什麼這個散列被凍結,但是如果'#options =#'setter是可訪問的,那麼你可以重複這個散列。或者合併並覆蓋('options = options.merge(...)') –

+0

哦,而且'map'沒有任何意義,它會返回一個數組'':client_id,:client_id,...]'替換它每個' –

+0

'NoMethodError:undefined method'options ='for#':( –

回答

0

最後破解它。關鍵是_validate_callbacks

def scope_validators(foreign_key) 
    new_callback_chain = self._validate_callbacks.reject do |callback| 
    callback.raw_filter.is_a?(ActiveRecord::Validations::UniquenessValidator) 
    end 
    deleted = self._validate_callbacks - new_callback_chain 
    (self._validate_callbacks.clear << new_callback_chain).flatten! 
    deleted.each do |c| 
    v = c.raw_filter 
    v.attributes.each do |a| 
     validates_uniqueness_of *v.attributes, v.options.merge(scope: foreign_key) 
    end 
    end 
end 

工程就像混入模型的款待。