声明一个枚举属性,其中值在数据库中映射为整数,但可以通过名称进行查询。示例
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-th 元素映射到 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 方法和 predicate 方法以及相关的范围现在都相应地带有前缀和/或后缀。
conversation.active_status! conversation.archived_status? # => false conversation.comments_inactive! conversation.comments_active? # => false
如果您想禁用模型上自动生成的方法,可以通过将 :instance_methods 选项设置为 false 来实现。
class Conversation < ActiveRecord::Base enum :status, [ :active, :archived ], instance_methods: false end
默认情况下,在分配无效值时将引发 ArgumentError。
class Conversation < ActiveRecord::Base enum :status, [ :active, :archived ] end conversation = Conversation.new conversation.status = :unknown # 'unknown' is not a valid status (ArgumentError)
如果希望在保存之前验证枚举值,请使用 :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
- E