Как показать сериализованный атрибут Array для модели Rails ActiveRecord в форме?
Мы используем функцию "serialize" ActiveRecord в Rails, например:
class User < ActiveRecord::Base
serialize :favorite_colors, Array
....
end
Итак, мы можем иметь
u = User.last
u.favorite_colors = [ 'blue', 'red', 'grey' ]
u.save!
Таким образом, в основном ActiveRecord сериализует массив выше и сохраняет его в одном поле базы данных с именем favorite_colors.
Мой вопрос: как вы позволяете пользователю вводить свои любимые цвета в форме?
Вы используете серию текстовых полей? И как только они будут введены, как вы показываете их в форме для редактирования?
Это вопрос, связанный с помощниками формы Rails для атрибута сериализованного массива.
Спасибо
Ответы
Ответ 1
Если вы хотите многоточечное поле HTML, попробуйте:
= form_for @user do |f|
= f.select :favorite_colors, %w[full colors list], {}, :multiple => true
Если вы используете simple_form gem, вы можете легко представить варианты:
= simple_form_for @user do |f|
= f.input :favorite_colors, as: :check_boxes, collection: %w[full colors list]
Ответ 2
Чтобы разрешить доступ к атрибутам AR, вы должны предоставить их следующим образом:
class User < ActiveRecord::Base
serialize :favorite_colors, Array
attr_accessible :favorite_colors
....
end
Ответ 3
Я решил эту проблему, "сглаживая" массив в представлении и
восстановление массива в контроллере.
В модели также требуются некоторые изменения, см. ниже.
class User < ActiveRecord::Base
serialize :favorite_colors, Array
def self.create_virtual_attributes (*args)
args.each do |method_name|
10.times do |key|
define_method "#{method_name}_#{key}" do
end
define_method "#{method_name}_#{key}=" do
end
end
end
end
create_virtual_attributes :favorite_colors
end
Если вы не определяете такие методы, как указано выше, Rails будет жаловаться на элемент формы
имена в представлении, например "favorite_colors_0" (см. ниже).
В представлении я динамически создаю 10 текстовых полей, favorite_colors_0, favorite_colors_1 и т.д.
<% 10.times do |key| %>
<%= form.label :favorite_color %>
<%= form.text_field "favorite_colors_#{key}", :value => @user.favorite_colors[key] %>
<% end %>
В контроллере я должен объединить текстовые поля favorite_colors_ * в массив, прежде чем звонить
save или update_attributes:
unless params[:user].select{|k,v| k =~ /^favorite_colors_/}.empty?
params[:user][:favorite_colors] = params[:user].select{|k,v| k =~ /^favorite_colors_/}.values.reject{|v| v.empty?}
params[:user].reject! {|k,v| k=~ /^favorite_colors_/}
end
Одна вещь, которую я делаю, это жесткий код 10, который ограничивает количество элементов, которые вы можете иметь в массиве favorite_colors. В форме он также выводит 10 текстовых полей. Мы можем легко изменить 10 - 100. Но у нас все еще будет предел. Ваше предложение о том, как удалить этот предел, приветствуется.
Надеюсь, вы сочтете это сообщение полезным.