2013-07-17 53 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