Ruby-on-rails 从表单中选择枚举以设置角色
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24193814/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Select enum from form to set role
提问by DDDD
Ruby on Rails 4.1
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 set the enum role.
我正在使用具有枚举角色的设计。它当前在创建用户时设置默认角色。我想在创建用户的表单中添加一个字段来设置枚举角色。
I read thisbut it doesn't say how to utilize the new roles.
我读过这篇文章,但没有说明如何利用新角色。
This is the User class
这是用户类
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
This is the part of the form where I am trying to have a select to pick an enum role:
这是我尝试选择枚举角色的表单的一部分:
<div class="form-group">
<%= f.collection_select :role, User.roles, :id, :enum, {prompt: "Select a role"}, {class: "form-control input-lg"} %>
</div>
The error:
错误:
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'
I have never used enum before and the documentationis not proving helpful. How do I make the enum options show?
我以前从未使用过 enum 并且文档证明没有帮助。如何使枚举选项显示?
回答by Daniel Kehoe
To start, enumis not the name of an attribute. The name of the attribute is role.
首先,enum不是属性的名称。属性的名称是role。
Take a look at the rails-devise-punditexample application, specifically the file app/views/users/_user.html.erbwhich 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_selectfor helper (that is suitable if you have a separate Role model). Instead, an ordinary selectform helper will work.
查看rails- devise-pundit示例应用程序,特别是文件app/views/users/_user.html.erb,它是创建表单以允许管理员更改用户角色的部分文件。我怀疑您是否想使用collection_selectfor 助手(如果您有单独的角色模型,这很合适)。相反,一个普通的select表单助手将起作用。
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 mapmethod.
该语句从 User 模型中获取一个角色数组,并使用该map方法构造一个键值对数组。
回答by Mohamad
Since you are using Rails 4 or higher, enums are even less complicated.
由于您使用的是 Rails 4 或更高版本,枚举甚至更简单。
Given the following enum:
鉴于以下枚举:
enum role: {
admin: 1
}
Enums expect the HTML option attribute valueto be the enum key:
枚举期望 HTML 选项属性value是枚举键:
<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.
然后使用 CSS 您可以修改外观。
.user-roles-select option {
text-transform: capitalize;
}
回答by Yan Foto
The cleanest way that I've come with in order to use collection_selectwith enums is the following:
我为了collection_select与enums一起使用而采用的最干净的方法如下:
f.collection_select :diet_preference, User.roles.map{ |dp| [dp.first, dp.first.humanize] }, :first, :second
回答by Mene
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 :
这是我如何做到的,国际化和排序,如果已经定义,则自动选择 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" } %>
回答by Means
As enum is a wrapper for integer in Rails, and I wanted to store strings in DB instead, I did the following:
由于 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] }
}
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'.
由于我正在使用可以声明预定义数据类型的 PostGREsql 服务器,因此我将一个名为“year”的列附加到“year”类型的 Child 模型中。
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:migratefor DB migration changes.
最后,rails db:migrate对于数据库迁移更改。
So, now rails enum can be used to store strings in DB.
因此,现在可以使用 rails enum 将字符串存储在 DB 中。

