Сохранение перечисления из select в Rails 4.1
Я использую перечисления в Rails 4.1, чтобы отслеживать цвет вина.
вино.РБ
class Wine < ActiveRecord::Base
enum color: [:red, :white, :sparkling]
end
на мой взгляд, я создаю select, чтобы пользователь мог выбрать вино с определенным цветом
f.input :color, :as => :select, :collection => Wine.colors
это создает следующий HTML:
<select id="wine_color" name="wine[color]">
<option value=""></option>
<option value="0">red</option>
<option value="1">white</option>
<option value="2">sparkling</option>
</select>
однако, при отправке формы, я получаю ошибку аргумента с указанием '1' is not a valid color
. Я понимаю, что это потому, что color
должен быть равен 1
, а не "1"
.
Is есть способ заставить Rails интерпретировать цвет как целое число, а не строку?
7 ответов:
хорошо, так что, по-видимому, вы не должны отправлять целочисленное значение перечисления для сохранения. Вы должны отправить текстовое значение перечисления.
Я изменил ввод следующим образом:
f.input :color, :as => :select, :collection => Wine.colors.keys.to_a
который сгенерировал следующий HTML:
<select id="wine_color" name="wine[color]"> <option value=""></option> <option value="red">red</option> <option value="white">white</option> <option value="sparkling">sparkling</option> </select>
значения перешли от" 0 "к" красному", и теперь мы все настроены.
если вы используете обычный ol ' rails text_field это:
f.select :color, Wine.colors.keys.to_a
если вы хотите иметь чистые человекочитаемые атрибуты, которые вы также можете сделать:
f.select :color, Wine.colors.keys.map { |w| [w.humanize, w] }
нет необходимости преобразовывать хэш перечисления в массив с помощью
to_a
. Этого достаточно:f.select :color, Wine.colors.map { |key, value| [key.humanize, key] }
принятое решение не работает для меня удобочитаемом, но я смог заставить его работать так:
<%= f.select(:color, Wine.colors.keys.map {|key| [key.humanize, key]}) %>
Это был самый чистый, но мне действительно нужно было очеловечить мои ключи:
<%= f.select(:color, Wine.colors.keys) %>
Я просто собрал EnumHelper, который я думал, что поделюсь, чтобы помочь людям, которым нужны более настраиваемые метки перечисления и локали для выбора вашего перечисления.
module EnumHelper def options_for_enum(object, enum) options = enums_to_translated_options_array(object.class.name, enum.to_s) options_for_select(options, object.send(enum)) end def enums_to_translated_options_array(klass, enum) klass.classify.safe_constantize.send(enum.pluralize).map { |key, value| [I18n.t("activerecord.enums.#{klass.underscore}.#{enum}.#{key}").humanize, key] } end end
на вашем языке:
en: activerecord: enums: wine: color: red: "Red Wine" white: "White Wine"
в виде:
<%= f.select(:color, options_for_enum(@wine, :color)) %>
если вы используете перечисление в Rails 4, то просто позвоните
Model.enums
:f.select :color, Wine.colors.keys
для создания HTML:
<select name="f[color]" id="f_color"> <option value="red">red</option> <option value="white">white</option> <option value="sparkling"> sparkling </option> </select>
или добавить метод в контроллер:
def update_or_create change_enum_to_i .... end def change_enum_to_i params[:f]["color"] = params[:f]["color"].to_i end
Если вам нужно обрабатывать i18n на основе ключей перечисления вы можете использовать:
<%= f.select :color, Wine.colors.keys.map {|key| [t("wine.#{key}"), key]} %>
и в транляциях вы можете установить цвета:
wine: red: Red white: White
вот мое решение (мои роли имеют подчеркивания в них, как "sales_rep"), и по какой-то причине это было так, как мне нужно было получить пустой вариант для работы (с simpleform?):
В ApplicationHelper:
def enum_collection_for_select(attribute, include_blank = true) x = attribute.map { |r| [r[0].titleize, r[0]] } x.insert(0,['', '']) if include_blank == true x end
потом в моей форме:
<%= f.input :role, collection: enum_collection_for_select(User.roles), selected: @user.role %>