声明一个枚举属性,其中值映射到数据库中的整数,但可以通过名称查询。示例
class Conversation < ActiveRecord::Base
enum :status, [ :active, :archived ]
end
# conversation.update! status: 0
conversation.active!
conversation.active? # => true
conversation.status # => "active"
# conversation.update! status: 1
conversation.archived!
conversation.archived? # => true
conversation.status # => "archived"
# conversation.status = 1
conversation.status = "archived"
conversation.status = nil
conversation.status.nil? # => true
conversation.status # => nil
基于枚举字段允许值的范围也将提供。使用上面的示例
Conversation.active
Conversation.not_active
Conversation.archived
Conversation.not_archived
当然,如果您不需要范围,也可以直接查询它们
Conversation.where(status: [:active, :archived])
Conversation.where.not(status: :active)
可以通过将:scopes
设置为false
来禁用定义范围。
class Conversation < ActiveRecord::Base
enum :status, [ :active, :archived ], scopes: false
end
您可以通过设置:default
来设置默认的枚举值,例如
class Conversation < ActiveRecord::Base
enum :status, [ :active, :archived ], default: :active
end
conversation = Conversation.new
conversation.status # => "active"
可以使用哈希显式映射属性和数据库整数之间的关系
class Conversation < ActiveRecord::Base
enum :status, active: 0, archived: 1
end
最后,也可以使用字符串列来持久化枚举值。请注意,这可能会导致数据库查询变慢
class Conversation < ActiveRecord::Base
enum :status, active: "active", archived: "archived"
end
请注意,当使用数组时,从值到数据库整数的隐式映射是从值在数组中出现的顺序派生的。在示例中,:active
映射到0
,因为它是第一个元素,:archived
映射到1
。通常,第i
个元素映射到数据库中的i-1
。
因此,一旦将值添加到枚举数组中,就必须保持它在数组中的位置,并且新值只能添加到数组的末尾。要删除未使用的值,应使用显式的哈希语法。
在极少数情况下,您可能需要直接访问映射。映射通过一个具有复数属性名称的类方法公开,该方法返回一个ActiveSupport::HashWithIndifferentAccess
Conversation.statuses[:active] # => 0
Conversation.statuses["archived"] # => 1
当您需要知道枚举的序数值时,请使用该类方法。例如,当手动构建 SQL 字符串时,您可以使用它
Conversation.where("status <> ?", Conversation.statuses[:archived])
当您需要定义具有相同值的多个枚举时,可以使用:prefix
或:suffix
选项。如果传递的值为true
,则方法会以枚举的名称为前缀/后缀。也可以提供自定义值
class Conversation < ActiveRecord::Base
enum :status, [ :active, :archived ], suffix: true
enum :comments_status, [ :active, :inactive ], prefix: :comments
end
使用上面的示例,bang 和谓词方法以及相关的范围现在已相应地加上了前缀和/或后缀
conversation.active_status!
conversation.archived_status? # => false
conversation.comments_inactive!
conversation.comments_active? # => false
如果您想在模型上禁用自动生成的 method,可以通过将:instance_methods
选项设置为 false 来实现
class Conversation < ActiveRecord::Base
enum :status, [ :active, :archived ], instance_methods: false
end
如果您希望在保存之前验证枚举值,请使用选项:validate
class Conversation < ActiveRecord::Base
enum :status, [ :active, :archived ], validate: true
end
conversation = Conversation.new
conversation.status = :unknown
conversation.valid? # => false
conversation.status = nil
conversation.valid? # => false
conversation.status = :active
conversation.valid? # => true
也可以传递其他验证选项
class Conversation < ActiveRecord::Base
enum :status, [ :active, :archived ], validate: { allow_nil: true }
end
conversation = Conversation.new
conversation.status = :unknown
conversation.valid? # => false
conversation.status = nil
conversation.valid? # => true
conversation.status = :active
conversation.valid? # => true
否则将引发ArgumentError
class Conversation < ActiveRecord::Base
enum :status, [ :active, :archived ]
end
conversation = Conversation.new
conversation.status = :unknown # 'unknown' is not a valid status (ArgumentError)
- E
实例公共方法
enum(name, values = nil, **options) 链接
来源: 显示 | 在 GitHub 上
# File activerecord/lib/active_record/enum.rb, line 216 def enum(name, values = nil, **options) values, options = options, {} unless values _enum(name, values, **options) end