Wie kann ein Dropdown-Feld <Auswahl> in einem Schienenformular erstellt werden?

76

Ich erstelle ein Gerüst -

rails g scaffold Contact email:string email_provider:string 

Ich möchte jedoch, dass der E-Mail-Anbieter ein Dropdown-Menü (mit Google Mail / Yahoo / MSN als Optionen) und kein Textfeld ist. Wie kann ich das machen ?

iCyborg
quelle

Antworten:

88

Sie können sich die Rails-Dokumentation ansehen . Wie auch immer, in Ihrer Form:

  <%= f.collection_select :provider_id, Provider.order(:name),:id,:name, include_blank: true %>

Wie Sie sich vorstellen können, sollten Sie E-Mail-Anbieter in einem anderen Modell vordefinieren, um herauszufinden Provider, wo Sie sie auswählen können.

R Milushev
quelle
Das Modell wird also contact.rb sein, aber wo soll ich diese Dropdown-Logik platzieren? Entschuldigung für die naive Frage, ich bin neu in der RoR-Entwicklung
iCyborg
1
Ihre Frage ist in Ordnung. Wenn Sie sich die Struktur Ihrer ansehen app/views/contacts, finden Sie eine Datei _form.html.erb. Sie können versuchen, es dort zu platzieren. Diese "Teilansicht" ist für das Erstellen und Aktualisieren von Aktionen des von Ihnen generierten Gerüsts zuständig.
R Milushev
3
Es wird empfohlen, die Reihenfolge (: Name) in einen Bereich (eine Methode) im Modell zu verschieben. Es ist hier keine große Sache, aber im Laufe der Zeit werden Sie feststellen, dass das, was im Wesentlichen eine Geschäftslogik wie diese (Bestellung) auf einer Ansichtsvorlage ist, zu einem Chaos wird. Verschieben Sie es zum Controller oder idealerweise zum Modell und stellen Sie dort einen Bereich zur Verfügung, den Sie verwenden können. Ein Beispiel: Wenn Sie am Ende drei Bildschirme oder Vorlagen haben, die das Dropdown-Menü verwenden, bedeutet die Reihenfolge in den Ansichten eine dreifache Duplizierung. Wenn Sie es im Modell haben, wird es an einem Ort definiert, und dies ist der einzige Ort, an dem Sie es ändern können, was gut ist.
Michael Durrant
52

Oder für benutzerdefinierte Optionen

<%= f.select :desired_attribute, ['option1', 'option2']%>
Fdwillis
quelle
6
<% = f.select: gewünschtes_Attribut, options_for_select ([['opt1'], ['opt2']]) Dies funktioniert für mich
longJOURNEY
16

Sie erstellen die Sammlung im ContactController -

app/controllers/contacts_controller.erb 

Hinzufügen

@providers = Provider.all.by_name

zu den neuen Methoden erstellen und bearbeiten, wobei ein Bereich für die by_nameim ProviderModell - app/models/provider.rb- für die Reihenfolge nach Namen verwendet wird

scope by_name  order(:name)

Dann in der Ansicht - app/views/contacts/_form.html.erb- verwenden Sie

<%= f.collection_select :provider_id, @providers, :id, :name, include_blank: true %>

Für Schienenformulare empfehle ich außerdem dringend, dass Sie sich einen Formularersteller wie simple_form ( https://github.com/plataformatec/simple_form) ansehen, der das gesamte schwere Heben übernimmt.

Michael Durrant
quelle
Vielen Dank, Michael. Ich habe die Frage bearbeitet und einen anderen Code eingefügt, der für mich funktioniert hat. Ich frage mich also, was der Unterschied bei der Verwendung von Select und collection_select ist, wie in den folgenden Antworten erwähnt.
iCyborg
9

Dies ist ein langer Weg, aber wenn Sie noch nicht implementiert haben, können Sie Ihre Modelle ursprünglich auf diese Weise erstellen. Die folgende Methode beschreibt das Ändern einer vorhandenen Datenbank.

1) Erstellen Sie ein neues Modell für die E-Mail-Anbieter:
$ rails g model provider name

2) Dadurch wird Ihr Modell mit einer Namenszeichenfolge und Zeitstempeln erstellt. Außerdem wird die Migration erstellt, die wir dem Schema hinzufügen müssen mit:
$ rake db:migrate

3) Fügen Sie eine Migration hinzu, um die Anbieter-ID zum Kontakt hinzuzufügen:
$ rails g migration AddProviderRefToContacts provider:references

4) Gehen Sie die Migrationsdatei durch, um zu überprüfen, ob sie in Ordnung ist, und migrieren Sie auch diese:
$ rake db:migrate

5) Okay, jetzt haben wir eine provider_id, wir brauchen nicht mehr die ursprüngliche email_provider-Zeichenfolge:
$ rails g migration RemoveEmailProviderFromContacts

6) Fügen Sie in der Migrationsdatei die Änderung hinzu, die ungefähr so ​​aussieht:

class RemoveEmailProviderFromContacts < ActiveRecord::Migration
  def change
    remove_column :contacts, :email_provider
  end
end

7) Migrieren Sie anschließend die Änderung:
$ rake db:migrate

8) Nehmen wir uns diesen Moment Zeit, um unsere Modelle zu aktualisieren:
Kontakt: belongs_to :provider
Anbieter:has_many :contacts

9) Dann richten wir die Dropdown-Logik im Teil _form.html.erb in den Ansichten ein:

  <div class="field">
    <%= f.label :provider %><br>
    <%= f.collection_select :provider_id, Provider.all, :id, :name %>
  </div>

10) Schließlich müssen wir die Prüfer selbst hinzufügen. Eine Möglichkeit, dies zu tun, wäre die Verwendung der Seed-Datei:

Provider.destroy_all

gmail = Provider.create!(name: "gmail")
yahoo = Provider.create!(name: "yahoo")
msn = Provider.create!(name: "msn")

$ rake db:seed

Phobos
quelle
6

<%= f.select :email_provider, ["gmail","yahoo","msn"]%>

gsumk
quelle
5

Bitte schauen Sie hier

Entweder können Sie Rails-Tags verwenden oder einfache HTML-Tags

Schienen-Tag

<%= select("Contact", "email_provider", Contact::PROVIDERS, {:include_blank => true}) %>

* Über der Codezeile wird HTML-Code (HTML-Tag). Finden Sie ihn unten. *

HTML-Tag

<select name="Contact[email_provider]">
  <option></option>
  <option>yahoo</option>
  <option>gmail</option>
  <option>msn</option>
</select>
Raghvendra Parashar
quelle
danke, ich bin immer noch verwirrt, ich verstehe, dass der <select> -Code in _form.html.erb gespeichert wird, aber wohin geht dieser Auswahlcode ("Contact",)?
iCyborg
3

In Ihrem Modell

class Contact
  self.email_providers = %w[Gmail Yahoo MSN]
  validates :email_provider, :inclusion => email_providers
end

In Ihrer Form,

<%= f.select :email_provider, 
    options_for_select(Contact.email_providers, @contact.email_provider) %>

Für das zweite Argument von options_for_select wird ein aktueller email_provider ausgewählt.

konyak
quelle
2

Schienen werden mithilfe der Zuordnung has_many für Artikel und Kategorie abgelegt:

has_many :articles

belongs_to :category

<%= form.select :category_id,Category.all.pluck(:name,:id),{prompt:'select'},{class: "form-control"}%>
Sivamani
quelle