2014-06-12 11 views
9

Ruby on Rails 4.1Seleziona enum dal modulo per impostare il ruolo

Sto utilizzando Devise con il ruolo enum. Attualmente imposta un ruolo defunto quando viene creato l'utente. Voglio aggiungere un campo al modulo che crea utenti per impostare il ruolo enum.

Ho letto this ma non dice come utilizzare i nuovi ruoli.

Questa è la classe utente

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 

Questa è la parte del modulo in cui sto cercando di avere una selezione per scegliere un ruolo enum:

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

L'errore:

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' 

Non ho mai usato enum prima e the documentation non si è rivelato utile. Come faccio a mostrare le opzioni enum?

risposta

20

Per iniziare, enum non è il nome di un attributo. Il nome dell'attributo è role.

Date un'occhiata a l'applicazione rails-devise-pundit esempio, in particolare il file app/views/utenti/_user.html.erb che è un parziale, che crea un modulo per consentire all'amministratore di cambiare il ruolo di un utente. Dubito che tu voglia usare un collection_select per l'helper (che è adatto se hai un modello di Ruolo separato). Invece, un normale helper di modulo select funzionerà.

Ecco un semplice esempio che hardcodes alle impostazioni ruolo:

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

Ecco un esempio migliore che evita hardcoding i ruoli nella forma:

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

L'istruzione ottiene una serie di ruoli da il modello Utente e costruisce un array di coppie chiave-valore usando il metodo map.

+0

L'unica cosa che rimane da fare è sovrascrivere il Devise :: RegistrationsController # create per consentire il ruolo ora. +1 – DDDD

+0

Non è necessario sovrascrivere il controller delle registrazioni. Puoi farlo nel controller dell'applicazione. Vedi il mio [Rails Devise Tutorial] (http://railsapps.github.io/rails-devise/) o il [README di sviluppo] (https://github.com/plataformatec/devise). –

+0

Penso di averlo fatto in modo non-pigro. Ho creato un utente: RegistrationsController con un before_filter: configure_permitted_parameters che sanitizer.for (: sign_up) Se inserisco quel codice potresti farmi sapere se è un modo sicuro di farlo? – DDDD

3

Il modo più pulito che sono venuto con, al fine di utilizzare collection_select con enum s è la seguente:

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

Dal momento che si sta utilizzando Rails 4 o superiore, enumerazioni sono ancor meno complicato.

Dati i seguenti enum:

enum role: { 
    admin: 1 
} 

Enums aspettano l'attributo opzione HTML value essere la chiave enum:

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

Sapendo questo, è possibile passare nelle chiavi enum.

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

Quindi utilizzando il CSS è possibile modificare l'aspetto.

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

Ecco come ho fatto, con l'internazionalizzazione e l'ordinazione, e auto selezionare il ruolo current_user se già definito. Si presuppone che un file locale con ruoli: categoria che contiene tutti i tuoi ruoli enum come ad esempio:

# 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" } %> 
0

Come enum è un wrapper per intero in Rails, e volevo conservare le stringhe nel DB, invece, ho ha fatto la seguente:

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

nella mia forma,

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

Mentre stavo usando server PostgreSQL in cui un tipo di dati predefinito può essere dichiarata, ho aggiunti una colonna chiamata 'anno' al modello Child di type'year '.

rails generate migration AddYearToChildren year:year 

e modificato il file di migrazione come di seguito.

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 

Infine, rails db:migrate per le modifiche di migrazione DB.

Quindi, ora enum rails può essere utilizzato per memorizzare stringhe in DB.