从Rails 4.1中的select中保存枚举

时间:2014-05-15 18:43:24

标签: ruby-on-rails ruby ruby-on-rails-4 enums

我正在使用Rails 4.1中的枚举来跟踪葡萄酒的颜色。

Wine.rb

class Wine < ActiveRecord::Base
    enum color: [:red, :white, :sparkling]
end

在我看来,我生成一个选择,以便用户可以选择具有特定颜色的葡萄酒

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"

有没有办法强制Rails将颜色解释为整数而不是字符串?

9 个答案:

答案 0 :(得分:188)

好吧,显然,你不应该发送要保存的枚举的整数值。您应该发送枚举的文本值。

我将输入更改为以下内容:

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>

值来自&#34; 0&#34; to&#34; red&#34;现在我们已经全部准备好了。


如果你正在使用普通的ol&#39; rails text_field it&#39; s:

f.select :color, Wine.colors.keys.to_a


如果您想拥有干净的人类可读属性,您也可以这样做:

f.select :color, Wine.colors.keys.map { |w| [w.humanize, w] }

答案 1 :(得分:28)

无需将枚举哈希值转换为to_a的数组。这足够了:

f.select :color, Wine.colors.map { |key, value| [key.humanize, key] }

答案 2 :(得分:9)

对于人类可读,已接受的解决方案对我没有用,但我能够让它像这样工作:

<%= f.select(:color, Wine.colors.keys) %>

这是最干净的,但我真的需要将我的钥匙人性化:

workingButton.setStyleName(BaseTheme.BUTTON_LINK);
workingButton.setIcon(new FileResource(new File(basepath + "help.png")));

答案 3 :(得分:8)

我刚刚整理了一个我想分享的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}"), key]
    }
  end

end

在您的语言区域中:

 en:
   activerecord:
     enums:
      wine:
        color:
          red:   "Red Wine"
          white:  "White Wine"

在您的观点中:

 <%= f.select(:color, options_for_enum(@wine, :color)) %>

答案 4 :(得分:5)

如果您在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

答案 5 :(得分:3)

这是对我有用的Rails 4 +:

class Contract < ApplicationRecord

enum status: { active:  "active", 
               ended: "active", 
               on_hold: "on_hold", 
               terminated:  "terminated", 
               under_review:  "under_review" , 
               unknown: "unknown" 
              }


end

my _form.html.erb中,我有这个:

  <div class="field">
    <%= form.select :status, Contract.statuses.keys, {}%>
  </div>
添加记录后从控制台进行

测试:

2.3.0 :001 > Contract.last.status
  Contract Load (0.2ms)  SELECT  "contracts".* FROM "contracts" ORDER BY "contracts"."id" DESC LIMIT ?  [["LIMIT", 1]]
 => "active"

答案 6 :(得分:2)

如果你需要根据枚举键处理i18n,你可以使用:

<%= f.select :color, Wine.colors.keys.map {|key| [t("wine.#{key}"), key]} %>

在翻译中你可以设置颜色:

wine:
 red: Red
 white: White

答案 7 :(得分:1)

这是我的解决方案(我的角色在其中有下划线,如&#34; sales_rep&#34;),由于某种原因,这就是我需要一个空白选项才能工作(使用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 %>

答案 8 :(得分:0)

对我来说,以下方法也有效:

= f.input :color, collection: Wine.colors.keys.map{ |key| [key.humanize, key] }, include_blank: false