Я использую Rails 3.2.0.rc2 . У меня Model
есть статика, Array
которую я предлагаю через форму, чтобы пользователи могли выбрать подмножество Array
и сохранить свой выбор в базе данных, хранящейся в одном столбце в Model
. Я использовал сериализацию для столбца базы данных, в котором хранится, Array
и Rails правильно конвертирует выбор пользователей в Yaml (и обратно в массив при чтении этого столбца). Я использую форму ввода с множественным выбором, чтобы сделать выбор.
Моя проблема в том, что в моем нынешнем виде все работает так, как я ожидал, за исключением того, что массив подмножества пользователя всегда имеет пустой первый элемент, когда он отправляется на сервер.
Это не имеет большого значения, и я мог бы написать код, чтобы вырезать это постфактум, но мне кажется, что я просто делаю какую-то синтаксическую ошибку, поскольку мне не кажется, что поведение Rails по умолчанию будет намеренно добавьте этот пустой элемент без какой-либо причины. Должно быть, я что-то пропустил или забыл отключить какую-то настройку. Пожалуйста, помогите мне понять, чего мне не хватает (или укажите на какую-нибудь хорошую документацию, которая описывает это более подробно, чем то, что я смог найти на интертубах).
Таблица базы данных MySQL 'модели':
- включает столбец с именем,
subset_array
который является ТЕКСТОВЫМ полем
Модель класса включает следующие параметры:
serialize :subset_array
ALL_POSSIBLE_VALUES = [value1, value2, value3, ...]
Форма для редактирования Модели включает следующие варианты ввода:
f.select :subset_array, Model::ALL_POSSIBLE_VALUES, {}, :multiple => true, :selected => @model.subset_array
PUT на сервер от клиента выглядит примерно так:
- предполагая, что выбраны только value1 и value3
"model" => { "subset_array" => ["", value1, value3] }
Обновление базы данных выглядит так:
UPDATE 'models' SET 'subset_array' = '--- \n- \"\"\n- value1\n- value3\n'
Как видите, в массиве, который отправляется и устанавливается в базе данных, есть этот дополнительный пустой элемент. Как мне от этого избавиться? Есть ли параметр, который мне не хватает в моем f.select
вызове?
Большое спасибо оценили :)
РЕДАКТИРОВАТЬ : это сгенерированный HTML-код из f.select
инструкции. Похоже, создается скрытый ввод, который может быть причиной моей проблемы? Почему это там?
<input name="model[subset_array][]" type="hidden" value>
<select id="model_subset_array" multiple="multiple" name="model[subset_array][]" selected="selected">
<option value="value1" selected="selected">Value1</option>
<option value="value2">Value2</option>
<option value="value3" selected="selected">Value3</option>
<option...>...</option>
</select>
источник
f.select
генерируемый фрагмент HTML ? Кроме того, такое поведение происходит даже при создании или только при обновлении?f.select
include_hidden: false
имеют ошибку. Когда вы удаляете все значения из поля выбора, идиоматикаmodel.update(something_params)
не будет включать это поле. TL; DR вы не сможете сделать поле пустым.Ответы:
Скрытое поле - это то, что вызывает проблему. Но на это есть веская причина: когда все значения не выбраны, вы все равно получаете параметр subset_array. Из документации Rails (возможно, вам придется прокрутить вправо, чтобы увидеть все это):
# The HTML specification says when +multiple+ parameter passed to select and all options got deselected # web browsers do not send any value to server. Unfortunately this introduces a gotcha: # if an +User+ model has many +roles+ and have +role_ids+ accessor, and in the form that edits roles of the user # the user deselects all roles from +role_ids+ multiple select box, no +role_ids+ parameter is sent. So, # any mass-assignment idiom like # # @user.update_attributes(params[:user]) # # wouldn't update roles. # # To prevent this the helper generates an auxiliary hidden field before # every multiple select. The hidden field has the same name as multiple select and blank value. # # This way, the client either sends only the hidden field (representing # the deselected multiple select box), or both fields. Since the HTML specification # says key/value pairs have to be sent in the same order they appear in the # form, and parameters extraction gets the last occurrence of any repeated # key in the query string, that works for ordinary forms.
РЕДАКТИРОВАТЬ: последний абзац предполагает, что вы не должны видеть пустой в случае, когда что-то выбрано, но я думаю, что это неправильно. Человек, совершивший эту фиксацию в Rails (см. Https://github.com/rails/rails/commit/faba406fa15251cdc9588364d23c687a14ed6885 ), пытается проделать тот же трюк, который Rails использует для флажков (как упоминалось здесь: https://github.com / rails / rails / pull / 1552 ), но я не думаю, что он может работать для поля множественного выбора, потому что в этом случае параметры, отправленные поверх, образуют массив, и поэтому никакое значение не игнорируется.
Так что я чувствую, что это ошибка.
источник
В Rails 4:
Вы сможете пройти
:include_hidden
вариант. https://github.com/rails/rails/pull/5414/filesВ качестве быстрого исправления на данный момент: вы можете прямо сейчас использовать в своей модели:
before_validation do |model| model.subset_array.reject!(&:blank?) if model.subset_array end
Это просто удалит все пустые значения на уровне модели.
источник
В Rails 4+ установите: include_hidden в select_tag в значение false
<%= form.grouped_collection_select :employee_id, Company.all, :employees, :name, :id, :name, { include_hidden: false }, { size: 6, multiple: true } %>
источник
Еще одно быстрое решение - использовать этот фильтр контроллера:
def clean_select_multiple_params hash = params hash.each do |k, v| case v when Array then v.reject!(&:blank?) when Hash then clean_select_multiple_params(v) end end end
Этот способ можно повторно использовать в контроллерах, не затрагивая слой модели.
источник
http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-check_box
Чтобы удалить пустые значения:
def myfield=(value) value.reject!(&:blank?) write_attribute(:myfield, value) end
источник
В контроллере:
arr = arr.delete_if { |x| x.empty? }
источник
Я исправил это с
params[:review][:staff_ids].delete("")
помощью контроллера перед обновлением.По-моему:
= form_for @review do |f| = f.collection_select :staff_ids, @business.staff, :id, :full_name, {}, {multiple:true} = f.submit 'Submit Review'
В моем контроллере:
class ReviewsController < ApplicationController def create .... params[:review][:staff_ids].delete("") @review.update_attribute(:staff_ids, params[:review][:staff_ids].join(",")) .... end end
источник
Я заставил его работать, написав это в части страницы Javascript:
$("#model_subset_array").val( <%= @model.subset_array %> );
Мой больше похож на следующий:
$("#modela_modelb_ids").val( <%= @modela.modelb_ids %> );
Не уверен, что в будущем это вызовет у меня головную боль, но теперь все работает нормально.
источник
Используйте jQuery:
$('select option:empty').remove();
Возможность удалить пустые параметры из раскрывающегося списка.
источник