web-dev-qa-db-fra.com

Sélectionner l'énumération du formulaire pour définir le rôle

Ruby on Rails 4.1

J'utilise Devise avec un rôle enum. Il définit actuellement un rôle par défaut lors de la création de l'utilisateur. Je souhaite ajouter un champ au formulaire qui crée des utilisateurs pour définir le rôle enum.

J'ai lu ceci mais cela ne dit pas comment utiliser les nouveaux rôles.

C'est la classe utilisateur

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

C’est la partie du formulaire où j’essaie de choisir un rôle enum:

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

L'erreur:

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'

Je n'ai jamais utilisé enum auparavant et la documentation n'est pas utile. Comment puis-je afficher les options enum? 

11
DDDD

Pour commencer, enum n'est pas le nom d'un attribut. Le nom de l'attribut est role.

Jetez un coup d’œil à l’application Rails-devise-pundit example, plus précisément au fichier app/views/users/_user.html.erb qui est un partiel qui crée un formulaire permettant à changer le rôle d'un utilisateur. Je doute que vous souhaitiez utiliser un collection_select pour helper (qui convient si vous avez un modèle de rôle distinct). Au lieu de cela, un assistant de forme select ordinaire fonctionnera.

Voici un exemple simple qui code les options de rôle:

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

Voici un meilleur exemple qui évite de coder en dur les rôles sous la forme:

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

L'instruction obtient un tableau de rôles à partir du modèle utilisateur et construit un tableau de paires clé-valeur à l'aide de la méthode map.

30
Daniel Kehoe

Puisque vous utilisez Rails 4 ou supérieur, les énumérations sont encore moins compliquées.

Étant donné l'énumération suivante:

enum role: {
  admin: 1
}

Enums s'attend à ce que l'attribut d'option HTML value soit la clé enum:

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

Sachant cela, vous pouvez passer les clés enum.

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

Ensuite, en utilisant CSS, vous pouvez modifier l'apparence.

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

La manière la plus propre que j'ai utilisée pour utiliser collection_select avec enums est la suivante:

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

Voici comment je l'ai fait, avec l'internationalisation et la commande, et la sélection automatique du rôle current_user si déjà défini.

# 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

Comme enum est un wrapper pour un entier dans Rails et que je voulais plutôt stocker des chaînes dans une base de données, j'ai procédé comme suit:

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

Sous ma forme,

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

Comme j'utilisais le serveur PostGREsql dans lequel un type de données prédéfini peut être déclaré, j'ai ajouté une colonne appelée "année" au modèle Child de type "année".

 Rails generate migration AddYearToChildren year:year

et changé le fichier de migration comme ci-dessous.

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

Enfin, Rails db:migrate pour les changements de migration de base de données. 

Ainsi, Rails enum peut maintenant être utilisé pour stocker des chaînes dans la base de données.

1
Means