在 Rails 4 中,如何在初始化模型时引用枚举值?

In Rails 4, how do I reference an enum value when initializing my model?

我正在使用 Rails 4.2。目前无法升级。我有这个型号

class OrderItem < ApplicationRecord
    …
  enum type: { data: “Data”, product: “Product” }

如何通过引用我的枚举来初始化我的对象?我试过这个

@order_item = OrderItem.new(
  order_item_params.merge(
    type: :product
  )
)
…
@order_item.save

但这会导致错误

 NoMethodError:
   undefined method `safe_constantize' for :product:Symbol

我猜你 运行 陷入了 STI 冲突,而不是 enum 问题。 Rails 为 Single Table Inheritance (STI) 保留 type 列名称并使用 type 存储 class 名称,但您正在尝试存储 Symbol在 type。 ActiveRecord 尝试将 type 值转换为 class,因此投诉无法在您的 :product 符号上调用 safe_constantize

您可以为您的列使用不同的名称或告诉 ActiveRecord 为 STI 使用不同的名称(可能是您永远不会使用的名称):

class OrderItem < ApplicationRecord
  self.inheritance_column = '_type'
  ...
end

我认为 self.inheritance_column = nil 也适用于 Rails4,我知道 nil 适用于 Rails6 但我不确定 Rails 4.

TLDR:

class OrderItem < ApplicationRecord
  self.inheritance_column = 'definitely_not_type'
  enum type: { data: "Data", product: "Product" }

type 是 Rails 中 inheritance_column 的默认值。该栏目主要用于Single Table Inheritance。当它存在时,ActiveRecord 将使用此列中的值作为它从数据库中获取的每一行的 class。

因此给定 table animals 具有这些值:

id | type   | name
------------------------
1  | Cat    | Mr Mittens
2  | Dog    | Laika
3  | Snake  | Snek

当您调用 Animal.all.map {|m| m.class} 时,您将得到 [Cat, Dog, Snake]。或者至少如果这些内容确实存在,你会的。

如果您实际上并没有使用 STI 并且想使用名称 type,您可以将任何您想要的分配给 self.inheritance_column