Rails 4.1의 select에서 열거 형 저장


108

와인의 색상을 추적하기 위해 Rails 4.1의 열거 형을 사용하고 있습니다.

Wine.rb

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".

Rails가 색상을 문자열이 아닌 정수로 해석하도록 강제하는 방법이 있습니까?

답변:


203

좋아, 분명히 저장할 열거 형의 정수 값을 보내지 말아야합니다. 열거 형의 텍스트 값을 보내야합니다.

입력을 다음과 같이 변경했습니다.

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"에서 "red"로 변경되었으며 이제 모든 설정이 완료되었습니다.


일반 ol 'rails text_field를 사용하는 경우 다음과 같습니다.

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


사람이 읽을 수있는 깨끗한 속성을 원한다면 다음을 수행 할 수도 있습니다.

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


8
FWIW, 나는 배열을 나타 내기 f.select :color, Wine.colors.to_a.map { |w| [w[0].humanize, w[0]] }때문에 그것을 만들어야했습니다 w. 이유는 모르겠지만 아마도 이것이 누군가를 도울 것입니다.
jakealbaugh

사용하여 titleize두 개 이상의 단어가 있으면 더 좋은 생각이 될 수 있습니다
안와르

8
keys(가) 그래서 방법은 배열을 반환 to_a중복됩니다. 또는 select helper 메서드는 옵션에 대해 2D 배열을 사용하므로 to_a.
xander-miller

"ERROR_JUNK_Submission"과 같은 잘못된 문자열이 전송되면 어떻게됩니까? 분명히 이와 같은 열거 형 값은 없으며 예외가 발생합니다. 어디에서 잡을까요?
FlyingV 2015

모델 Wine에는 color라는 열거 형이 enum color: [:red, :white, :sparkling]있으므로 올바른 문장은f.input :color, :as => :select, :collection => Wine.color.keys.to_a
hguzman

32

열거 형 해시를 to_a. 이것으로 충분합니다.

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

10

열거 형 선택에 대해 더 많은 사용자 지정 열거 형 레이블 및 로캘이 필요한 사람들을 돕기 위해 공유 할 것으로 생각되는 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)) %>

1
편집은 번역 키를 더 읽기 multiplewordclassname보다는 오히려 전형적인 multiple_word_class_name에서 MultipleWordClassName에 속하는 열거 찾아합니다
Tetsujin없이 오니

우아한 대체의 기본에 추가하는 방법에 대한 방법 : [I18n.t("activerecord.enums.#{klass.underscore}.#{enum}.#{key}", default: key.humanize), key] 또한, 지난 제거 humanize는 여러 단어 경우는 대소 문자를 왜곡시킬 수로
피터 P.

9

허용되는 솔루션은 사람이 읽을 수 있도록 나를 위해 작동하지 않았지만 다음과 같이 작동하도록 만들 수 있습니다.

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

이것은 가장 깨끗했지만 키를 인간화해야했습니다.

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

1
이제 5에서 지원하는 가장 깨끗한 방법을 레일
V-SHY

@ V-SHY,이게 뭐야, 설명해 줄래?
ismailarilik

2
@ismailarilik 직접 선택 옵션으로 키를 제공, <% = f.select (: 색상, Wine.colors.keys) %>
V-SHY

6

Rails 4에서 enum을 사용하는 경우 다음을 호출하십시오 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

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

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"

3

열거 형 키를 기반으로 i18n을 처리해야하는 경우 다음을 사용할 수 있습니다.

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

변환에서 색상을 설정할 수 있습니다.

wine:
 red: Red
 white: White

1

내 솔루션은 다음과 같습니다 (내 역할에는 "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 %>
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.