2013-12-09 62 views
1

我有一個模型,使用回調標準化其參數之一,該參數是模型的唯一鍵的一部分。但是當使用MyModel.find_or_create_by()時,回調不會在'發現'階段發揮作用,只有'創建'階段,這是爲時已晚。find_or_create_by與before_save回調

有沒有這樣做的優雅模式?一個人爲的例子:

class CreateMyModels < ActiveRecord::Migration 
    def change 
    create_table :my_models do |t| 
     t.float :value 
    end 
    add_index :my_models, :value, :unique => true 
    end 
end 

class MyModel < ActiveRecord::Base 
    before_save :quantize_value 
    private 
    def quantize_value 
     self.value = ((self.value || 0.0) * 256.0).round/256.0 
    end 
end 

讓我們嘗試一下:

>> a = MyModel.find_or_create_by(:value => 0.501) 
=> #<MyModel id: 1, value: 0.5> 

到目前爲止,一切都很好。如果我們找到另一個價值接近但不等於現任記錄的人,我們希望它找到現任記錄。而是我們得到:

>> b = MyModel.find_or_create_by(:value => 0.5001) 
PG::UniqueViolation: ERROR: duplicate key value violates unique constraint ... 

我想什麼 - 概念 - 是有quantize_value方法運行之前運行的發現。

當然,我已經寫了一個自定義構造函數,在運行find之前應用quantize_value方法。但是如果經驗教會了我什麼,那就是Rails的開發人員已經編寫了我認爲我需要編寫的代碼,創建自己的構造函數將複製他們的工作! :)

回答

0

國際海事組織,我會移動模型的量化邏輯保存回調,並手動執行。你會更清楚實際值是什麼,而不是設置一個值,然後看到模型修改它。

如果你真的想保持模型內部的邏輯,你可以覆蓋setter方法爲您的屬性如下圖所示:

def value=(val) 
    self[:value] = quantitize_value(val) 
end 
+0

「移動量化邏輯出來的車型」 - 這是值得商榷的:我他聲稱量化值是模型的函數,不應該暴露給調用者。但是我正在按照你提出的建議使用MyModel中的自定義構造函數來隱藏調用者的細節。 –

+0

如果你真的想保留這個模型,然後嘗試覆蓋你的值集方法,如def value =(val); @值= quantitize_value(值);結束(取代;確實是換行符) –

+0

這聽起來恰到好處。如果你編輯你的答案,我會接受它。 –