17

Ruby on Rails 4.1

我正在使用带有枚举角色的设计。它当前在创建用户时设置默认角色。我想在创建用户的表单中添加一个字段来设置枚举角色。

我读了这篇文章,但没有说明如何利用新角色。

这是用户类

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

这是我试图选择一个枚举角色的表单的一部分:

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

错误:

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'

我以前从未使用过枚举,并且文档证明没有帮助。如何使枚举选项显示?

4

5 回答 5

40

首先,enum不是属性的名称。属性的名称是role

看一下rails-devise- pundit示例应用程序,特别是文件app/views/users/_user.html.erb,它是创建表单以允许管理员更改用户角色的部分。我怀疑你想使用一个collection_selectfor 助手(如果你有一个单独的角色模型,那是合适的)。相反,一个普通的select表单助手将起作用。

这是一个对角色选项进行硬编码的简单示例:

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

这是一个更好的示例,可以避免对表单中的角色进行硬编码:

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

map该语句从 User 模型中获取一个角色数组,并使用该方法构造一个键值对数组。

于 2014-06-12T22:54:07.630 回答
10

由于您使用的是 Rails 4 或更高版本,因此枚举甚至更简单。

给定以下枚举:

enum role: {
  admin: 1
}

枚举期望 HTML 选项属性value是枚举键:

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

知道了这一点,您可以传入枚举键。

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

然后使用 CSS 你可以修改外观。

.user-roles-select option {
  text-transform: capitalize;
}
于 2015-05-01T14:48:03.717 回答
7

collection_select为了与s一起使用,我提供的最干净enum的方法如下:

f.collection_select :diet_preference, User.roles.map{ |dp| [dp.first, dp.first.humanize] }, :first, :second
于 2015-01-15T14:20:16.170 回答
2

这是我的做法,国际化和排序,如果已经定义,则自动选择 current_user 角色。它假定您有一个带有角色的语言环境文件:包含所有枚举角色的类别,例如:

# 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" } %>
于 2016-08-19T22:23:14.917 回答
1

由于 enum 是 Rails 中整数的包装器,而我想将字符串存储在 DB 中,因此我执行了以下操作:

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

以我的形式,

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

当我使用可以声明预定义数据类型的 PostGREsql 服务器时,我在类型为“year”的子模型中附加了一个名为“year”的列。

 rails generate migration AddYearToChildren year:year

并更改了迁移文件,如下所示。

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

最后,rails db:migrate对于 DB 迁移更改。

因此,现在可以使用 rails 枚举在 DB 中存储字符串。

于 2017-05-03T09:09:36.507 回答