Rails 6 : class 中的枚举

Rails 6 : Enum within a class

我正在努力使我的目录在 class 中使用枚举,来自这个教程:https://naturaily.com/blog/ruby-on-rails-enum

我的模特:

**app/models/catalog.rb**
class Catalog < ApplicationRecord
  include ArrayToEnumHash
  enum state: array_to_enum_hash(CatalogState::STATES)

  def state
    @state ||= CatalogState.new(read_attribute(:state))
  end
end
**app/models/catalog_state.rb**
class CatalogState
  STATES = %w(incoming in_progress finished).freeze

  def initialize(state)
    @state = state
  end

  # what you need here
end
**app/concerns/array_to_enum_hash.rb**
module ArrayToEnumHash
  extend ActiveSupport::Concern
  def array_to_enum_hash(array)
    result = {}
    v = array.to_enum
    w = array.map {|v| v.to_sym }.to_enum
    loop do
      result[w.next] = v.next
    end
    result
  end
end
**db/schema.rb**
create_enum :catalog_state, [
    "incoming",
    "in_progress",
    "finished",
  ]

create_table "catalogs", force: :cascade do |t|
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.enum "state", enum_name: "catalog_state"
    t.index ["state"], name: "index_catalogs_on_state"
  end

我的目录看起来不错:

#<Catalog:0x00007fe87dbfb810
 id: 3,
 created_at: Thu, 02 Jul 2020 16:52:36 UTC +00:00,
 updated_at: Fri, 03 Jul 2020 19:51:26 UTC +00:00,
 status: "unset",
 auction_type: "internet",
 state: "in_progress">

但是,在我的控制台上,ActiveRecord 没有构建枚举快捷方式:

[5] pry(main)> c.state
=> "in_progress"
[6] pry(main)> c.in_progress?
NoMethodError: undefined method `in_progress?' for #<Catalog:0x00007fe87dbfb810>
from /Users/pierre/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/activemodel-6.0.3.2/lib/active_model/attribute_methods.rb:432:in `method_missing'

卧槽?

您不需要那么多就可以在您的目录中添加“枚举”列 table。

class CreateCatalogs < ActiveRecord::Migration[6.0]
  def change
    create_table :catalogs do |t|
      t.string "status"
      t.string "auction_type"
      t.integer "state"
      t.timestamps
    end
  end
end

枚举列可以用 integer 数据类型列表示,t.integer "state"

为了设置枚举值,您可以调用 CatalogState 中定义的常量:

class Catalog < ApplicationRecord
  enum state: CatalogState::STATES
end

值将为 ["incoming", "in_progress", "finished"],否则,在关注点中使用辅助方法将类似于 {:incoming=>"incoming", :in_progress=>"in_progress", :finished=>"finished"},并且 Rails 无法推断整数他们代表的价值。

之后可以试一下:

catalog = Catalog.new(id: 3, created_at: 'Thu, 02 Jul 2020 16:52:36 UTC +00:00', updated_at: 'Fri, 03 Jul 2020 19:51:26 UTC +00:00', status: 'unset', auction_type: 'internet', state: 'in_progress')
catalog.valid? # true
catalog.save
Catalog.last
# Catalog Load (0.3ms)  SELECT "catalogs".* FROM "catalogs" ORDER BY "catalogs"."id" DESC LIMIT   [["LIMIT", 1]]
# => #<Catalog:0x00007fc4d9448f90 id: 3, status: "unset", auction_type: "internet", state: "in_progress", created_at: Thu, 02 Jul 2020 16:52:36 UTC +00:00, updated_at: Fri, 03 Jul 2020 19:51:26 UTC +00:00>
Catalog.last.in_progress?
# Catalog Load (0.5ms)  SELECT "catalogs".* FROM "catalogs" ORDER BY "catalogs"."id" DESC LIMIT   [["LIMIT", 1]]
# => true