web-dev-qa-db-de.com

Wählen Sie aus dem Formular eine Aufzählung aus, um die Rolle festzulegen

Ruby on Rails 4.1

Ich benutze Devise mit Enum-Rolle. Es legt derzeit eine definierte Rolle fest, wenn der Benutzer erstellt wird. Ich möchte dem Formular ein Feld hinzufügen, das Benutzer erstellt, um die Aufzählungsrolle festzulegen.

Ich habe this gelesen, aber es sagt nicht aus, wie man die neuen Rollen nutzen kann.

Dies ist die Benutzerklasse

devise :database_authenticatable, :registerable, :confirmable,
     :recoverable, :rememberable, :trackable, :validatable
enum role: [:user, :vip, :admin, :developer, :marketing, :support, :translator]
after_initialize :set_default_role, :if => :new_record?

def set_default_role
  self.role ||= :user
end

Dies ist der Teil des Formulars, in dem ich versuche, eine Enumerationsrolle auszuwählen:

<div class="form-group">
  <%= f.collection_select :role, User.roles, :id, :enum, {Prompt: "Select a role"}, {class: "form-control input-lg"} %>
</div>

Der Fehler:

NoMethodError - undefined method `enum' for ["user", 0]:Array:
actionview (4.1.1) lib/action_view/helpers/form_options_helper.rb:761:in `value_for_collection'

Ich habe noch nie enum verwendet und die Dokumentation erweist sich nicht als hilfreich. Wie kann ich die Enum-Optionen anzeigen lassen? 

11
DDDD

enum ist nicht der Name eines Attributs. Der Name des Attributs lautet role.

Schauen Sie sich die Beispielanwendung Rails-devise-pundit an, insbesondere die Datei app/views/users/_user.html.erb , die ein Teil darstellt, das ein Formular erstellt, das den Administrator zulässt Ändern Sie die Rolle eines Benutzers. Ich bezweifle, dass Sie einen collection_select für den Helfer verwenden möchten (der sich eignet, wenn Sie ein separates Rollenmodell haben). Stattdessen funktioniert ein normaler select-Formularhelfer.

Hier ist ein einfaches Beispiel, das die Rollenoptionen fest codiert:

<%= f.select(:role, [['User', 'user'], ['Vip', 'vip'], ['Admin', 'admin']]) %>

Hier ist ein besseres Beispiel, das das Festcodieren der Rollen im Formular vermeidet:

<%= f.select(:role, User.roles.keys.map {|role| [role.titleize,role]}) %>

Die Anweisung bezieht ein Rollenarray aus dem Benutzermodell und erstellt mithilfe der map-Methode ein Array aus Schlüsselwertpaaren.

30
Daniel Kehoe

Da Sie Rails 4 oder höher verwenden, sind die Aufzählungen noch weniger kompliziert.

Angesichts der folgenden Aufzählung:

enum role: {
  admin: 1
}

Aufzählungen erwarten, dass das HTML-Optionsattribut value der Aufzählungsschlüssel ist:

<option value="admin"> <!-- As opposed to: <option value="1"> -->

Wenn Sie dies wissen, können Sie die Enum-Schlüssel übergeben.

<%= f.select :role, User.roles.keys, {}, class: 'user-roles-select' %>

Mit CSS können Sie dann das Erscheinungsbild ändern.

.user-roles-select option {
  text-transform: capitalize;
}
9
Mohamad

Die sauberste Methode, die ich zur Verwendung von collection_select mit enums verwendet habe, ist die folgende:

f.collection_select :diet_preference, User.roles.map{ |dp| [dp.first, dp.first.humanize] }, :first, :second
5
Yan Foto

So habe ich es gemacht, mit Internationalisierung und Sortierung, und automatisch die aktuelle Benutzerrolle auswählen, falls bereits definiert. Es wird davon ausgegangen, dass Sie über eine Länderdatei mit einer Rollenkategorie verfügen, die alle Ihre Enumerationsrollen enthält:

# your locale file
en:
 roles:
  admin: "Administrator"
  mode: "Moderator"


# model user.rb
enum role: { admin: 0, mode: 1 }
ROLES = User.roles.map { |r,| [I18n.t("roles.#{r}"), r] }.sort_by { |r| I18n.t("roles.#{r}") }

# view

<%= f.select :role, User::ROLES, { Prompt: t("users.roles.Prompt"), selected: @user.role }, { class: "form-control" } %>
2
Mene

Da enum ein Wrapper für Integer in Rails ist und ich stattdessen Strings in DB speichern wollte, habe ich Folgendes getan:

    class Child < ApplicationRecord
       enum year: {
          Infant: 'Infant',
          '2-5_years': '2_to_5_years',
          '5-8_years': '5_to_8_years',
          '8-10_years': '8_to_10 years',
          'More_than_10_years': 'More_than_10_years'
       }
       AGE_YEARS = Child.years.map { |k, v| [k.humanize, v] }
     }

In meiner Form

<%= f.select :age, options_for_select(Child::AGE_YEARS, params[:age]), include_blank: 'Select an age-group.' %>

Da ich einen PostGREsql-Server verwendet habe, auf dem ein vordefinierter Datentyp deklariert werden kann, habe ich eine Spalte namens "year" an das Child-Modell des Typs "year" angehängt.

 Rails generate migration AddYearToChildren year:year

und änderte die Migrationsdatei wie folgt.

class AddYearToChildren < ActiveRecord::Migration[5.0]
  def up
    execute <<-SQL
      CREATE TYPE year AS ENUM ('Infant', '2_5_years', '5_8_years', '8_10_years', 'More_than_10_years');
    SQL
    add_column :children, :year, :year, index: true
  end

  def down
    remove_column :children, :year

    execute <<-SQL
      DROP TYPE year;
    SQL
  end
end

Schließlich Rails db:migrate für Änderungen der DB-Migration. 

Jetzt können Sie mit Rails enum Strings in DB speichern.

1
Means