2017-05-07 113 views
1

我有一個enum屬性verification_status使用幾類模塊:Rails的5:只讀枚舉屬性

included(self) do 
    enum verification_status: { dont_verify: 0, pending: 1, in_review: 2, rejected: 3, approved: 4 } 
end 

我想是隻讀這個屬性的方式,有會是沒有辦法修改它,除非通過一個專用的方法,即它應該失敗,併發生異常或返回一些錯誤。這裏的原因是我需要修改的另一個屬性,所以當有人在可驗證對象上調用add_verification(這是專用方法)時,帶有一些屬性的Verification被添加到先前列表中對該對象進行驗證,並且該對象的狀態設置爲verification_status

我知道attr_readonly,但這並不能真正涵蓋我所關心的所有情況。提前致謝!

回答

1

標準導軌代碼不支持只讀枚舉所以請考慮以下作爲一種破解。一般枚舉值可以通過兩種方式進行設置:

  • 通過直接設置一個值枚舉列名 - 這個行爲可以使用attr_readonly被抑制,因爲你說,但我想不會有什麼方法留下來實際上設置了的枚舉值;這就是爲什麼我們寧願自己重新定義setter方法,
  • 通過調用record.enum_value! - bang方法是動態定義的,必須重新定義以拋出錯誤而不是設置值。

所以,宣告enum後,您需要重新定義setter方法,大意如下:

enum verification_status: { dont_verify: 0, pending: 1, in_review: 2, rejected: 3, approved: 4 } 

# redefine the enum setter 
define_method("verification_status=") do |args = nil| 
    raise "use `add_verification` instead to modify this" 
end 

# redefine the bang enum setters 
verification_statuses.each do |status, value| 
    define_method("#{status}!") do 
    raise "use `add_verification` instead to modify this" 
    end 
end 

然後,實際設置枚舉值,則需要使用專用write_attribute方法使用枚舉枚舉值直接設置屬性,例如:

write_attribute(:verification_status, self.class.verification_statuses[:pending]) 
#=> 1 

# verify that the value has been indeed set 
verification_status 
#=> "pending" 
+0

我有一個關於'add_verification'方法正確性的問題。是否有一個更優雅/正確的方法來做到這一點(調用'save'最終看起來很奇怪): 'def add_verification(verification)' 'write_attribute(:verification_status,Verification.statuses [verification.status]) ' '驗證<<驗證' '保存' '末端' 如果我理解正確,'write_attribute'只修改內存中的屬性,而不保存到數據庫。這就是爲什麼我叫'保存'(抱歉格式不好,這是我能做的最好的)。 –

+1

更正,'write_attribute'只設置內存中的屬性,你必須調用'save'。爲什麼你看起來很奇怪? 'save'可能會存在一個問題,即保存所有更改的屬性(如果有),而不僅僅是驗證狀態。你也可以使用'update_column'方法,直接在db中設置屬性,參見[docs](http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update_column)爲更多。 – BoraMa

+0

我現在無法檢查它,但我認爲'''這裏還保存對'驗證'數組所做的更改。因此,如果使用'save',那麼數據庫更新就會重複,對嗎?如果是,在這種情況下'update_column'是更好的方法。堤防中! –