Ruby-on-rails 在 Rails 4.1 中从选择中保存枚举

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23686265/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 23:38:20  来源:igfitidea点击:

Saving enum from select in Rails 4.1

ruby-on-railsrubyruby-on-rails-4enums

提问by Brian Weinreich

I am using the enums in Rails 4.1 to keep track of colors of wine.

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

Wine.rb

葡萄酒.rb

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

In my view, I generate a select so the user can select a wine with a certain color

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

f.input :color, :as => :select, :collection => Wine.colors

This generates the following HTML:

这将生成以下 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>

However, upon submitting the form, I receive an argument error stating '1' is not a valid color. I realize this is because colormust equal 1and not "1".

但是,在提交表单时,我收到一个参数错误,说明'1' is not a valid color. 我意识到这是因为colormust equal1和 not "1"

Is there a way to force Rails to interpret the color as an integer rather than a string?

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

回答by Brian Weinreich

Alright, so apparently, you shouldn't send the integer value of the enum to be saved. You should send the text value of the enum.

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

I changed the input to be the following:

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

f.input :color, :as => :select, :collection => Wine.colors.keys.to_a

f.input :color, :as => :select, :collection => Wine.colors.keys.to_a

Which generated the following HTML:

其中生成了以下 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>

Values went from "0" to "red" and now we're all set.

值从“0”变为“红色”,现在我们都设置好了。



If you're using a regular ol' rails text_field it's:

如果您使用的是常规 ol' rails text_field,则为:

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

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



If you want to have clean human-readable attributes you can also do:

如果您想拥有干净的人类可读属性,您还可以执行以下操作:

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

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

回答by Fellow Stranger

No need converting the enum hash to array with to_a. This suffice:

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

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

回答by Andrew Cetinic

I just put together an EnumHelper that I thought I'd share to help people who need more customised enum labels and locales for your enum selects.

我只是整理了一个 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

In your locale:

在您的语言环境中:

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

In your views:

在您看来:

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

回答by Tom Rossi

The accepted solution didn't work for me for the human readable, but I was able to get it to work like this:

接受的解决方案对我的人类可读性不起作用,但我能够让它像这样工作:

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

This was the cleanest, but I really needed to humanize my keys:

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

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

回答by ogelacinyc

If you use enum in Rails 4 then just call Model.enums:

如果您在 Rails 4 中使用枚举,则只需调用Model.enums

f.select :color, Wine.colors.keys

To create HTML:

要创建 HTML:

<select name="f[color]" id="f_color">
    <option value="red">red</option>
    <option value="white">white</option>
    <option value="sparkling"> sparkling </option>
</select>

Or add method in controller:

或者在控制器中添加方法:

def update_or_create
    change_enum_to_i
    ....
end

def change_enum_to_i
    params[:f]["color"] = params[:f]["color"].to_i
end

回答by zee

Here is what worked for me, Rails 4+:

这是对我有用的,Rails 4+:

class Contract < ApplicationRecord

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


end

in my _form.html.erb, I have this:

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

  <div class="field">
    <%= form.select :status, Contract.statuses.keys, {}%>
  </div>

test from Console after adding a record:

添加记录后从控制台测试:

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

回答by Paulo Fidalgo

If you need to handle the i18n based on the enum keys you can use:

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

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

and in the tranlations you can set the colors:

在翻译中,您可以设置颜色:

wine:
 red: Red
 white: White

回答by Greg Blass

Here's my solution (my roles have underscores in them like "sales_rep"), and for some reason this was how I needed to get a blank option to work (with simpleform?):

这是我的解决方案(我的角色中有下划线,例如“sales_rep”),出于某种原因,这就是我需要获得一个空白选项才能工作的方式(使用 simpleform?):

In ApplicationHelper:

在 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

Then in my form:

然后以我的形式:

<%= f.input :role, collection: enum_collection_for_select(User.roles), selected: @user.role %>