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?
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.
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;
}
Die sauberste Methode, die ich zur Verwendung von collection_select
mit enum
s verwendet habe, ist die folgende:
f.collection_select :diet_preference, User.roles.map{ |dp| [dp.first, dp.first.humanize] }, :first, :second
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" } %>
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.