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
我正在努力使我的目录在 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