如何在关注中使用枚举

问题描述

我有这个(简化的)担忧:

module Nobi::Personable
  extend ActiveSupport::Concern

  included do
    belongs_to :person,:autosave => true    delegate :gender,:gender=,:gender_changed?,:gender_was,:to => :person,:allow_nil => true
    enum gender: { male: "male",female: "female" }
  end
end

居民有这种担忧。

现在,当我这样做时:

2.6.6> Resident.last.gender
  Resident Load (16.2ms)  SELECT "residents".* FROM "residents" ORDER BY "residents"."id" DESC LIMIT $1  [["LIMIT",1]]
  Person Load (16.1ms)  SELECT "people".* FROM "people" WHERE "people"."id" = $1 LIMIT $2  [["id",48],["LIMIT",1]]
 => "male"

但是当我问:男性?时,我得到了

2.6.6> Resident.last.male?
  Resident Load (17.0ms)  SELECT "residents".* FROM "residents" ORDER BY "residents"."id" DESC LIMIT $1  [["LIMIT",1]]
 => false

这怎么可能?

如果我在Person模型中包括该枚举,则可以正常工作:

Person.last.male?
  Person Load (15.9ms)  SELECT "people".* FROM "people" ORDER BY "people"."id" DESC LIMIT $1  [["LIMIT",1]]
 => true

我创建了一个简单的演示应用程序来演示此行为: https://github.com/rept/enum_app

r = Resident.create(gender: :male,local_gender: :local_male)
r.local_male?
 => true
r.male?
 => false

解决方法

声明一个枚举属性,其中值映射到 数据库,但可以按名称查询。
-ActiveRecord::Enum

您需要在枚举中使用整数列,或显式声明映射。 Rails假定数据库中存储的值等于传递给enum的数组的索引。由于"male" != 0 #male?将返回false。

module Nobi::Personable
  extend ActiveSupport::Concern

  included do
    belongs_to :person,:autosave => true
    enum gender: {
      male:   "male",female: "female"
    }
  end
end

虽然使用字符串列会失败,但首先要使用枚举来明确声明映射被视为最佳实践,因为这将避免调试仅通过重新排序枚举值可能导致的破损。数组。

如果您需要证明:

class User < ApplicationRecord
  enum gender: [:male,:female] # users.gender is an integer column
end
irb(main):003:0> User.first
   (0.9ms)  SELECT sqlite_version(*)
  User Load (2.0ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT",1]]
=> #<User id: 9,created_at: "2020-10-29 09:24:12",updated_at: "2020-10-29 09:24:12",gender: "male">
irb(main):004:0> User.first.male?
  User Load (0.2ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT",1]]
=> true
class Resident < ApplicationRecord
  # residents.gender is a string column
  enum gender: {
    male: 'male',female: 'female'
  }
end
irb(main):001:0> Resident.create!(gender: 'male')
   (0.4ms)  SELECT sqlite_version(*)
   (0.1ms)  begin transaction
  Resident Create (1.6ms)  INSERT INTO "residents" ("gender","created_at","updated_at") VALUES (?,?,?)  [["gender","male"],["created_at","2020-10-29 09:56:59.471917"],["updated_at","2020-10-29 09:56:59.471917"]]
   (4.7ms)  commit transaction
=> #<Resident id: 1,gender: "male",created_at: "2020-10-29 09:56:59",updated_at: "2020-10-29 09:56:59">
irb(main):002:0> Resident.first.male?
  Resident Load (0.2ms)  SELECT "residents".* FROM "residents" ORDER BY "residents"."id" ASC LIMIT ?  [["LIMIT",1]]
=> true

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...