2013-05-22 2 views
7

У меня есть модель в приложении Rails для Бюллетеня, и когда она создана, многие значения хранятся в базе данных как сериализованные хэши или массивы, к которым нужно получить доступ позже. Я пытаюсь создать представление редактирования только для одного из этих хэшей, но я не могу понять, как получить к нему доступ в моей форме.Как редактировать сериализованные хэши Rails в форме?

Хэш выглядит следующим образом при хранении:

top_offices = { first_office: "Office Name", first_office_amount: 1234.50, 
second_office: "Office Name", second_office_amount: 1234.50 } 

И так далее ... Есть пять отделений.

Таким образом, в консоли я могу изменить значение, выполнив:

bulletin = Bulletin.last 
bulletin.top_offices[:first_office] = "New Office" 
bulletin.top_offices[:first_office_amount] = 1234.00 
bulletin.save 

Я не могу понять, как сделать форму, которая позволяет мне присвоить эти значения правильно. Мне даже не нужна форма для заполнения ранее сохраненными значениями, потому что я меняю их полностью в любое время, когда использую форму.

ответ

8

Вариант 1: Одиночный метод экземпляра для обновления Сериализированного атрибута

Насколько я знаю, что это не возможно редактировать непосредственно из формы упорядоченного атрибута.

Когда у меня такие вещи, я всегда создаю метод экземпляра в модели, который получает параметры и выполняет обновление (также может делать сохранение, если я заканчиваю имя метода с помощью bang (!)).

В вашем случае я бы сделал следующее:

class Bulletin 

    ... 

    def update_top_offices!(params) 
    params.each do |key, value| 
     self.top_offices[key] = value 
    end 

    self.save 
    end 

    ... 
end 

Вариант 2: геттер/сеттер за сериализованными ключей атрибутов

Также другая возможность, если вы действительно хотите использовать форму, чтобы обновить сериализованные атрибут должен создать геттер/сеттер следующим образом:

class Bulletin 

    ... 

    def first_office 
    self.top_offices[:first_office] 
    end 

    def first_office=(value) 
    self.top_offices[:first_office] = value 
    end 

    ... 
end 

Но не забудьте сохранить обновленные значения.

Варианты 3: Перекрытие method_missing

Последняя возможность переопределить method_missing, но это немного сложнее.

+0

Хорошо. Я думаю, что смогу это выяснить, используя вариант один. Я, вероятно, предпочитаю второй подход, но я не могу понять, как это работает в моей голове. Как использовать эти методы в форме? Могу ли я просто создать 'form_tag' и некоторые' text_field_tag' для ': first_office' и т. Д., Как только я их определю, и отправьте на мое действие по обновлению? –

+1

Помощники вида * _field ищут имя данного атрибута для объекта, данного form_for. Поэтому, если вы сделали 'form_for @bulletin do | f |', а затем вы выполните 'f.text_field: first_office', то помощник' text_field' вызовет что-то с именем 'first_office' на объект.Это может быть атрибут или метод. Это «волшебная» часть;) – ZedTuX

5

Вот пример, который просто выполняет итерации по существующим парам ключ/значение в top_offices и создает для них поля формы.

<% @bulletin.top_offices.each do |key, value| %> 
    <input name="bulletin[top_offices][<%= key %>]" type="text" value="<%= value %>" /> 
<% end %> 

будет генерировать:

<input name="bulletin[top_offices][first_office]" ... /> 
<input name="bulletin[top_offices][first_office_amount]" ... /> 
# etc. 

Если вы не доверяете своим пользователям, то вы можете сделать проверку вменяемости на значения, представленные на top_offices.

Смежные вопросы