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.