2013-07-17 8 views
2

У меня есть модель DocumentType с атрибутом 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

Ключом к пониманию того, что происходит, является знание при сериализации. Проверяя serialization.rb в activerecord, вы увидите, что магия сериализации происходит путем переопределения type_cast_attribute_for_write, который вызывается на write_attribute. То есть при присвоении атрибута. Итак, когда вы делаете:

document_type.extensions = something 

что-то сериализуется и записывается в атрибут расширения. Это путь до сохранения. На самом деле вам даже не нужно вызывать save на document_type, чтобы атрибут был сериализован.

Лучшим обходным решением, которое я знаю, является переопределение extensions= на DocumentType. Кое-что вроде:

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

+1, солидный ответ здесь. Переписывать сеттера, безусловно, путь сюда. –

+0

Отличный ответ/объяснение! –

+0

Рад быть полезной. – boulder

-1

Я считаю, что это Append, потому что значение extensions сериализации в то время как модель подтверждено Rails, и ваш метод process_extensions называется позже (до модели сохраняется) и не действует, как ожидалось

Try использовать before_validate вместо

before_validate :process_extensions