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に色を文字列ではなく整数として解釈させる方法はありますか?
申し分なく、どうやら、保存する列挙の整数値を送信しないでください。列挙のテキスト値を送信する必要があります。
入力を次のように変更しました。
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}"), 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
ここに私のために働いたものがあります、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"
列挙キーに基づいて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 %>