我正在构建一个Ruby on Rails应用程序,其中我的模型属性是静态的,如Gender
和Status
。我决定将它们定义为模型中的enums
。我正在使用红宝石枚举宝石来定义枚举。
我已将红宝石宝石添加到我的项目中,并运行bundle install
:
gem 'ruby-enum', '~> 0.8.0'
但是,枚举需要由其他各种模型访问,因此我将枚举定义为模型的关注目录中的模块:
# app/models/concerns/status.rb
module Status
extend ActiveSupport::Concern
included do
include Ruby::Enum
define :ordered, 'Ordered'
define :cancelled, 'Cancelled'
define :waiting, 'Waiting'
end
end
我已将此模块包含在我的Users
模型中
class User < ApplicationRecord
include Status
end
我的Users
模型有一列用于status
:
create_table "users", force: :cascade do |t|
t.string "first_name"
t.string "last_name"
t.string "status"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
但是当我在rails console
中查询状态模块时:
Status.all
我收到错误:
NoMethodError (undefined method `all' for Status:Module)
当我还在 rails 控制台中查询所有statuses
的User
模型时:
User.statuses.all
我收到错误:
ArgumentError (wrong number of arguments (given 2, expected 0..1))
我也不知道如何在视图中提供此功能
# app/views/users/_form.html.erb
<%= form.label :status %><br />
<%= form.select :status, User.statuses.keys.collect { |status| status },{} %>
我将不胜感激在如何定义枚举并在用户表单视图中返回枚举的键值的正确方向上的一些帮助,以便可以在表单中选择状态。谢谢。
但是当我在 rails 控制台中查询状态模块时:
Status.all
我收到错误:
NoMethodError (undefined method `all' for Status:Module)
.all
要求提供 ActiveRecord 类的所有记录。Status
不是 ActiveRecord 类。它甚至不是一个类,它是一个模块。
至于User.statuses.all
,我没有看到statuses
在哪里定义。
Ruby::Enum
添加了一些常量和方法,但 Rails 不知道它们。你必须自己将它们集成到Rails中。
Rails已经集成了枚举。
module Status
extend ActiveSupport::Concern
included do
# It will take an Array, but it's good practice to be explicit.
enum status: {ordered: 0, cancelled: 1, waiting: 2}
end
end
User.statuses
将返回您的状态HashWithIndifferentAccess
。
请注意,这些枚举映射到整数,字符串会破坏枚举的点。将您的状态存储为整数可能会为您节省大量空间。Rails 将为您处理将整数映射到字符串并返回。
请务必将表更改为使用整数状态:t.string "status"
。要避免用户处于打开状态,您需要定义默认值或null: false
。
我想在视图页面中看到顺序而不是顺序。我想在视图页面中看到未订购和未not_ordered。我还希望状态的值存储在数据库中,而不是像 0、1、2 这样的整数。– 承诺普雷斯顿 12 秒前
数据显示方式的详细信息不属于数据库。最简单的事情是使用humanize
.
# ordered becomes Ordered. not_waiting becomes Not waiting.
User.statuses.keys.collect { |status| status.humanize }
您可以将其推送到状态模块中。
module Status
...
class_methods do
def show_statuses
statuses.keys.collect { |status| status.humanize }
end
end
end
User.show_statuses
将此作为选择...
<%= f.select :status, User.statuses.collect { |status,id| [status.humanize,id] } %>
你也可以把它推到状态。
module Status
...
class_methods do
...
def statuses_for_select
statuses.collect { |status,id| [status.humanize,id] }
end
end
end
<%= f.select :status, User.statuses_for_select %>
随着显示细节变得更加复杂,您的模型会变胖。然后,您需要考虑将其推入装饰器。