Rails - 使用 ActiveRecord::Enum 时出现 ArgumentError

Gok*_*l M 5 enums activerecord ruby-on-rails ruby-on-rails-5

我创建了一个Tester带有整数列的模型,tester_type并在模型中声明了 enum 变量。

class Tester < ApplicationRecord
  enum tester_type: { junior: 0, senior: 1, group: 2 }
end
Run Code Online (Sandbox Code Playgroud)

尝试为该模型创建/初始化对象时出现以下错误:

ArgumentError:您试图在模型“Tester”上定义一个名为“tester_type”的枚举,但这将生成一个类方法“group”,该方法已由 Active Record 定义。

所以,我尝试更改tester_type为,type_of_tester但它引发了相同的错误:

ArgumentError:您试图在模型“Tester”上定义一个名为“type_of_tester”的枚举,但这将生成一个类方法“group”,该方法已由 Active Record 定义。

我已经搜索了解决方案,我发现这个错误是ActiveRecord::Enum类中的一个常量ENUM_CONFLICT_MESSAGE,但是无法找到这个问题的原因。

请帮我。

谢谢。

小智 5

在这种情况下,如果您想使用枚举,最好将标签重命名为其他名称。这不是枚举所独有的——许多 Active Record 特性为你生成方法,通常没有办法选择退出这些生成的方法。

然后更改groupanother_name

或者你也应该遵循这个

enum :kind, [:junior, :senior, :group], prefix: :kind
band.kind_group?
Run Code Online (Sandbox Code Playgroud)


Was*_*ain 5

当您需要定义多个具有相同值的枚举或在您的情况下,您可以使用:_prefix:_suffix选项,以避免与已定义的方法发生冲突。如果传递的值为true,则方法以枚举的名称为前缀/后缀。也可以提供自定义值:

class Conversation < ActiveRecord::Base
  enum status: [:active, :archived], _suffix: true
  enum comments_status: [:active, :inactive], _prefix: :comments
end
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,bang 和 predicate 方法以及相关的范围现在相应地带有前缀和/或后缀:

conversation.active_status!
conversation.archived_status? # => false

conversation.comments_inactive!
conversation.comments_active? # => false
Run Code Online (Sandbox Code Playgroud)

对于您的情况,我的建议是使用以下内容:

class Tester < ApplicationRecord
  enum tester_type: { junior: 0, senior: 1, group: 2 }, _prefix: :type
end
Run Code Online (Sandbox Code Playgroud)

然后您可以将这些范围用作:

tester.type_group!
tester.type_group? # => true

Tester.type_group # SELECT "testers".* FROM "testers" WHERE "testers"."tester_type" = $1  [["tester_type", 2]]
# or,
Tester.where(tester_type: :group) # SELECT "testers".* FROM "testers" WHERE "testers"."tester_type" = $1  [["tester_type", 2]]
Run Code Online (Sandbox Code Playgroud)