Ruby on Rails: отправка массива в форме
У меня есть модель, которая имеет атрибут, который является массивом. Каким образом я могу заполнить этот атрибут из представления формы?
Я знаю, что есть ввод формы с полем, имя которого содержит скобки, создает хеш из ввода. Должен ли я просто взять это и пройти через него в контроллере, чтобы массировать его в массив?
Пример, чтобы сделать его менее абстрактным:
class Article
serialize :links, Array
end
Переменная ссылок принимает форму массива URL-адресов, т.е. [["http://www.google.com"], ["http://stackoverflow.com"]]
Когда я использую что-то вроде следующего в моей форме, он создает хэш:
<%= hidden_field_tag "article[links][#{url}]", :track, :value => nil %>
Полученный хеш выглядит следующим образом:
"links" => {"http://www.google.com" => "", "http://stackoverflow.com" => ""}
Если я не укажу URL-адрес в названии ссылки, дополнительные значения clobber друг друга:
<%= hidden_field_tag "article[links]", :track, :value => url %>
Результат выглядит следующим образом: "links" => "http://stackoverflow.com"
Ответы
Ответ 1
Если ваша форма html имеет поля ввода с пустыми квадратными скобками, они будут преобразованы в массив внутри параметров в контроллере.
# Eg multiple input fields all with the same name:
<input type="textbox" name="course[track_codes][]" ...>
# will become the Array
params["course"]["track_codes"]
# with an element for each of the input fields with the same name
Добавлено:
Обратите внимание, что помощники рельсов не настроены на автоматическое магнетическое трюк. Поэтому вам, возможно, придется вручную создавать атрибуты имени. Кроме того, флажки имеют свои проблемы при использовании помощников рельсов, поскольку хелпер-флажок создает дополнительные скрытые поля для обработки непроверенного случая.
Ответ 2
= simple_form_for @article do |f|
= f.input_field :name, multiple: true
= f.input_field :name, multiple: true
= f.submit
Ответ 3
TL; DR версия соглашения HTML []
:
Массив:
<input type="textbox" name="course[track_codes][]", value="a">
<input type="textbox" name="course[track_codes][]", value="b">
<input type="textbox" name="course[track_codes][]", value="c">
Получены парамы:
{ course: { track_codes: ['a', 'b', 'c'] } }
Hash
<input type="textbox" name="course[track_codes][x]", value="a">
<input type="textbox" name="course[track_codes][y]", value="b">
<input type="textbox" name="course[track_codes][z]", value="c">
Получены парамы:
{ course: { track_codes: { x: 'a', y: 'b', z: 'c' } }
Ответ 4
Я также узнал, что если вы передадите свой вспомогательный помощник, вы получите массив курсов, каждый со своими атрибутами.
# Eg multiple input fields all with the same name:
<input type="textbox" name="course[][track_codes]" ...>
# will become the Array
params["course"]
# where you can get the values of all your attributes like this:
params["course"].each do |course|
course["track_codes"]
end
Ответ 5
Я просто установил решение, используя jquery taginput:
http://xoxco.com/projects/code/tagsinput/
Я написал пользовательское расширение simple_form
# for use with: http://xoxco.com/projects/code/tagsinput/
class TagInput < SimpleForm::Inputs::Base
def input
@builder.text_field(attribute_name, input_html_options.merge(value: object.value.join(',')))
end
end
Фрагмент coffeescrpt:
$('input.tag').tagsInput()
И настройка моего контроллера, которая, к сожалению, должна быть немного специфичной:
@user = User.find(params[:id])
attrs = params[:user]
if @user.some_field.is_a? Array
attrs[:some_field] = attrs[:some_field].split(',')
end
Ответ 6
Для тех, кто использует простую форму, вы можете рассмотреть это решение. В основном необходимо настроить свой собственный вход и использовать его как: array. Затем вам нужно будет обрабатывать ввод на уровне вашего контроллера.
#inside lib/utitilies
class ArrayInput < SimpleForm::Inputs::Base
def input
@builder.text_field(attribute_name, input_html_options.merge!({value: object.premium_keyword.join(',')}))
end
end
#inside view/_form
...
= f.input :premium_keyword, as: :array, label: 'Premium Keyword (case insensitive, comma seperated)'
#inside controller
def update
pkw = params[:restaurant][:premium_keyword]
if pkw.present?
pkw = pkw.split(", ")
params[:restaurant][:premium_keyword] = pkw
end
if @restaurant.update_attributes(params[:restaurant])
redirect_to admin_city_restaurants_path, flash: { success: "You have successfully edited a restaurant"}
else
render :edit
end
end
В вашем случае просто измените: premium_keyword в поле вашего массива