Select enum from form to set role

前端 未结 5 1364
醉酒成梦
醉酒成梦 2021-02-01 22:38

Ruby on Rails 4.1

I am using Devise with enum role. It currently sets a defualt role when the User is created. I want to add a field to the form that creates Users to se

相关标签:
5条回答
  • 2021-02-01 23:06

    Here is how I did it, with internationalization and ordering, and auto select the current_user role if already defined. It assumes that you have a locale file with a roles: category containing all your enum roles such as :

    # 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 讨论(0)
  • 2021-02-01 23:10

    The cleanest way that I've come with in order to use collection_select with enums is the following:

    f.collection_select :diet_preference, User.roles.map{ |dp| [dp.first, dp.first.humanize] }, :first, :second
    
    0 讨论(0)
  • 2021-02-01 23:24

    To start, enum is not the name of an attribute. The name of the attribute is role.

    Take a look at the rails-devise-pundit example application, specifically the file app/views/users/_user.html.erb which is a partial that creates a form to allow the administrator to change a user's role. I doubt you want to use a collection_select for helper (that is suitable if you have a separate Role model). Instead, an ordinary select form helper will work.

    Here's a simple example that hardcodes the role options:

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

    Here is a better example that avoids hardcoding the roles in the form:

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

    The statement obtains an array of roles from the User model and constructs an array of key-value pairs using the map method.

    0 讨论(0)
  • 2021-02-01 23:25

    As enum is a wrapper for integer in Rails, and I wanted to store strings in DB instead, I did the following:

        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 my form,

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

    As I was using PostGREsql server wherein a pre-defined datatype can be declared, I appended a column called 'year' to the Child model of type'year'.

     rails generate migration AddYearToChildren year:year
    

    and changed the migration file as below.

    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
    

    Finally, rails db:migrate for DB migration changes.

    So, now rails enum can be used to store strings in DB.

    0 讨论(0)
  • 2021-02-01 23:32

    Since you are using Rails 4 or higher, enums are even less complicated.

    Given the following enum:

    enum role: {
      admin: 1
    }
    

    Enums expect the HTML option attribute value to be the enum key:

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

    Knowing this, you can pass in the enum keys.

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

    Then using CSS you can modify the appearance.

    .user-roles-select option {
      text-transform: capitalize;
    }
    
    0 讨论(0)
提交回复
热议问题