Сериализованное хэш-поле и простая форма
У меня есть следующее.
class Page < ActiveRecord::Base
belongs_to :category
serialize :fields
end
Значение Будет зависеть от категории. Но в качестве примера;
{"address" => "8 finance street, hong kong",
"founded" => "1973"}
В этом примере категория определила "address"
и "founded"
как пользовательские поля.
То, что я хочу сказать;
= simple_form_for(@page) do |f|
= f.association :category
- f.object.category.fields.each do |field|
= f.input field.name
Но мне нужно сделать что-то волшебное, чтобы справиться с тем фактом, что @page.founded
не является действительным
Вместо этого я должен смотреть на @page.fields["founded"]
.
Есть предложения?
Обновление:
У меня есть немного ближе
- if f.object.category
- f.object.category.fields.each do |field|
= f.input field.name do
= text_field_tag "post[fields][#{field.name}]", f.object.fields[file.name]
Теперь нужно сделать эту сушилку (не хочу указывать название объекта).
Я посмотрю, смогу ли я написать приличное простое расширение формы для этого.4 ответа:
Я столкнулся с подобной проблемой, пытаясь использовать
simple_fields_for
на типе хэш-поля Монгоидной модели. Монголоидная версия вашего примера, с которой я имел дело, выглядела так:class Page include Mongoid::Document field :fields, type: Hash end
Моя ситуация может быть немного иной, так как я уже знаю хэш-ключи, которые я ищу заранее, и просто необходим
simple_fields_for
для работы с хэш-полем. Наивный метод (basicfields_for
usage), который я использовал, выглядел так:Но это не заполняло форму должным образом. у николайдеса решение обертывания хэша в структуру сработало для меня:= simple_form_for(@page) do |f| = f.simple_fields_for :fields do |ff| = ff.input :address = ff.input :founded
- require 'ostruct' = simple_form_for(@page) do |f| = f.simple_fields_for :fields, OpenStruct.new(@page.fields) do |ff| = ff.input :address = ff.input :founded
Чтобы избежать необходимости смешивать материал OpenStruct в моем представлении, я создал monkey patch для
simple_form
, чтобы автоматически обернуть хэш-типы В OpenStruct и поместить его в инициализатор:require 'ostruct' module SimpleForm::ActionViewExtensions::Builder def simple_fields_for_with_hash_support(*args, &block) if args[0] && !args[1] field = object.send(args[0]) args << OpenStruct.new(field) if field.respond_to?(:has_key?) end simple_fields_for_without_hash_support(*args, &block) end alias simple_fields_for_without_hash_support simple_fields_for alias simple_fields_for simple_fields_for_with_hash_support end
И теперь я могу использовать свое оригинальное наивное решение без специального кода представления.
ИспользуйтеOpenStruct . Это работает следующим образом:
require 'ostruct' struct = OStruct.new("address" => "8 finance street, hong kong", "founded" => "1973") struct.address # => 8 struct.founded # => "1973"
Вот решение, которое вы можете легко адаптировать к вашей проблеме:
Https://gist.github.com/2157877
Сохраняет форму супер-чистой и сохраняет нормальное поведение активной модели (ничего добавить в контроллер).
Ура !
Если бы только я нашел этот пост раньше, я бы не пропустил три дня по этому вопросу.
Я не смог прокомментировать answear, поэтому просто добавить, если кто-то пытается
fields_for
массив mongo хэшей (has_many like) дополнительно вам нужно будет предоставить корневой объект OpenStruct с"#{key}_attributes="
(в этом случае fields_attributes=) метод, так чтоfields_for
будет идентифицировать это отношение has_many.Надеюсь, это кому-то поможет;)