Rails 4.1'deki seçimlerden numaralandırmayı kaydetme


108

Şarap renklerini takip etmek için Rails 4.1'deki numaralandırmaları kullanıyorum.

Wine.rb

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

Benim görüşüme göre, kullanıcının belirli bir renge sahip bir şarap seçebilmesi için bir seçim oluşturuyorum

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

Bu, aşağıdaki HTML'yi oluşturur:

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

Bununla birlikte, formu gönderdikten sonra, belirten bir argüman hatası alıyorum '1' is not a valid color. Bunun coloreşit olması 1ve olmaması gerektiğinin farkındayım "1".

Rails'i rengi bir dizeden ziyade tam sayı olarak yorumlamaya zorlamanın bir yolu var mı?

Yanıtlar:


203

Pekala, görünüşe göre, kaydedilecek numaranın tam sayı değerini göndermemelisiniz. Numaralandırmanın metin değerini göndermelisiniz.

Girişi şu şekilde değiştirdim:

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

Aşağıdaki HTML'yi oluşturan:

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

Değerler "0" dan "kırmızı" ya gitti ve şimdi hepimiz ayarlandık.


Normal bir ol 'rails text_field kullanıyorsanız:

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


İnsan tarafından okunabilir temiz niteliklere sahip olmak istiyorsanız şunları da yapabilirsiniz:

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


8
FWIW, bunu yapmam gerekiyordu f.select :color, Wine.colors.to_a.map { |w| [w[0].humanize, w[0]] }çünkü wbir diziyi temsil ediyordu. Neden olduğundan emin değilim, ama belki bu birine yardımcı olur.
— jakealbaugh

titleizeiki veya daha fazla kelimeniz varsa kullanmak daha iyi bir fikir olabilir
— Anwar

8
keysböylece usul bir dizi döner to_agereksizdir. Alternatif olarak, yardımcı seçme yöntemi seçenekler için 2B bir dizi alır, böylece yalnızca kullanabilirsiniz to_a.
— xander-miller

"ERROR_JUNK_Submission" gibi bir Geçersiz Dize gönderilirse ne olur? Açıkçası, bunun gibi bir enum değeri yoktur ve bir istisna atılır. Onu nerede yakalarız?
— FlyingV

Wine modelinde color adında bir sıralama vardır, enum color: [:red, :white, :sparkling]bu nedenle doğru cümlef.input :color, :as => :select, :collection => Wine.color.keys.to_a
— hguzman

32

Enum hash değerini diziye dönüştürmeye gerek yok to_a. Bu yeterli:

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

10

Numaralandırma seçimleriniz için daha özelleştirilmiş sıralama etiketlerine ve yerel ayarlara ihtiyaç duyan kişilere yardımcı olmak için paylaşacağımı düşündüğüm bir EnumHelper oluşturdum.

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

Bölgenizde:

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

Görüşlerinizde:

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

1
Düzenleme, multiplewordclassname yerine daha tipik multiple_word_class_name altında MultipleWordClassName'e ait enümleri bularak çeviri anahtarlarını daha okunabilir hale getirir
— Tetsujin no Oni

Zarif bir geri dönüş için varsayılan eklemeye ne dersiniz? [I18n.t("activerecord.enums.#{klass.underscore}.#{enum}.#{key}", default: key.humanize), key] Ayrıca, humanizebirden çok kelimesi varsa büyük harf kullanımını bozabileceğinden sonuncuyu kaldırın
— Peter P.

9

Kabul edilen çözüm, insan tarafından okunabilir için benim için işe yaramadı , ancak bunun şu şekilde çalışmasını sağladım:

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

Bu en temiziydi, ancak anahtarlarımı gerçekten insanlaştırmam gerekiyordu:

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

1
raylar 5 artık en temiz yolu destekliyor
— V-SHY

@ V-SHY, bu yol nedir, açıklayabilir misin?
— ismailarilik

2
@ismailarilik, doğrudan seçme seçeneği olarak anahtarları sağlamak, <% = f.select (: renk, Wine.colors.keys)%>
— V-SHY

6

Rails 4'te numaralandırmayı kullanırsanız şu numarayı arayın Model.enums:

f.select :color, Wine.colors.keys

HTML oluşturmak için:

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

Veya denetleyiciye yöntem ekleyin:

def update_or_create
    change_enum_to_i
    ....
end

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

4

İşte benim için işe yarayan şey, Rails 4+:

class Contract < ApplicationRecord

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


end

içinde my _form.html.erb, bende bu var:

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

bir kayıt ekledikten sonra Console'dan test edin:

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

İ18n'yi enum anahtarlarına göre işlemeniz gerekiyorsa, kullanabilirsiniz:

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

ve çevirilerde renkleri ayarlayabilirsiniz:

wine:
 red: Red
 white: White

1

İşte benim çözümüm (rollerimde "sales_rep" gibi alt çizgiler var) ve bazı nedenlerden dolayı, çalışmak için boş bir seçenek (basit form ile?)

ApplicationHelper'da:

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

Sonra formumda:

<%= f.input :role, collection: enum_collection_for_select(User.roles), selected: @user.role %>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.