2013-07-17 61 views
2

我有一個DocumentType模型w/a extensions屬性。在我的表單中,我允許人們將這些擴展插入到表單中。serialize&before_save in Rails 4

我希望能夠在保存之前解析輸入,剝離出任何無效選項,將其轉換爲數組並將Rails序列化。

我有下面的代碼,但我只是最終瓦特/輸入用戶的形式,而不是一個數組了:

class DocumentType < ActiveRecord::Base 
    serialize :extensions 

    before_save :process_extensions 

    def process_extensions 
    self.extensions = [*self.extensions.gsub(/[^a-z ]+/i, '').split(' ')].uniq 
    end 
end 
+0

你有沒有試過有一個psuedo屬性的字符串輸入設置數組,而不是將兩者合併到一個屬性? –

+0

我沒有。如果可能的話,我想避免這種情況,或者至少明白爲什麼我沒有得到我期望的結果。 –

+0

使用Ruby 1.9.3p392,Rails 4.0.0和Postgres測試你的代碼。代碼只是起作用。我已將擴展名設置爲「abc1 def abc!def」,讀完後得到[「abc」,「def」]。 –

回答

10

瞭解發生了什麼的關鍵是知道發生序列化時。通過檢查activerecord中的serialization.rb,你會發現序列化魔術是通過覆蓋type_cast_attribute_for_write來實現的,這在write_attribute上被調用。也就是屬性分配。所以當你這樣做的時候:

document_type.extensions = something 

東西被序列化並寫入擴展屬性。這是保存發生之前的方式。實際上,您甚至不必調用document_type上的保存來將該屬性序列化。

我知道的最佳解決方法是覆蓋DocumentType上的extensions=。就像:

def extensions=(value) 
    value = [*value.gsub(/[^a-z ]+/i, '').split(' ')].uniq 
    write_attribute :extensions, value 
end 
+0

+1,在這裏可靠的答案。覆蓋二傳手絕對是這裏的方式。 –

+0

優秀的答案/解釋! –

+0

很高興能有所幫助。 – boulder

-1

我相信這追加因爲extensions值,而連載模型由Rails的驗證,你process_extensions方法後來被稱爲(該模型保存前)和不作爲預期

嘗試before_validate改用

before_validate :process_extensions