Ruby on Rails 4.1
我正在使用具有枚举角色的Devise。它在创建用户时当前设置了defualt角色。我想在表单中添加一个字段,用于创建用户以设置枚举角色。
我读了this,但没有说明如何利用新角色。
这是用户类
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'
我之前从未使用过enum而且the documentation没有证明有用。如何显示枚举选项?
答案 0 :(得分:32)
首先,enum
不是属性的名称。该属性的名称为role
。
查看rails-devise-pundit示例应用程序,特别是文件 app / views / users / _user.html.erb ,这是部分创建表单以允许管理员改变用户的角色。我怀疑你想使用collection_select
帮助器(如果你有一个单独的角色模型,这是合适的)。相反,普通的select
表单帮助程序将起作用。
这是一个硬编码角色选项的简单示例:
<%= f.select(:role, [['User', 'user'], ['Vip', 'vip'], ['Admin', 'admin']]) %>
这是一个更好的示例,可以避免在表单中对角色进行硬编码:
<%= f.select(:role, User.roles.keys.map {|role| [role.titleize,role]}) %>
该语句从User模型获取一组角色,并使用map
方法构造一个键值对数组。
答案 1 :(得分:9)
由于您使用的是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;
}
答案 2 :(得分:6)
为了将collection_select
与enum
一起使用,我所采用的最简洁方法如下:
f.collection_select :diet_preference, User.roles.map{ |dp| [dp.first, dp.first.humanize] }, :first, :second
答案 3 :(得分: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" } %>
答案 4 :(得分: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
用于数据库迁移更改。
因此,现在rails enum可用于在DB中存储字符串。