【发布时间】:2020-03-20 23:27:56
【问题描述】:
我在我的模型上定义了一个ActiveRecord enum,如下所示:
class ApiKey < ApplicationRecord
enum api_version: { v1: -1, v2: 0, v3: 1 }
end
当我尝试通过枚举名称进行查询时,我注意到 ActiveRecord 没有正确构造查询。 例如
> ApiKey.where(owner_type: 'User', api_version: 'v3').to_sql
=> "SELECT \"api_keys\".* FROM \"api_keys\" WHERE \"api_keys\".\"owner_type\" = 'User' AND \"api_keys\".\"api_version\" = 0"
我指定了v3,所以我希望生成的查询能够正确地将其原始枚举值查找为1,但它使用的是0。
当然,我可以自己进行枚举映射并让它产生正确的结果:
> ApiKey.where(owner_type: 'User', api_version: ApiKey.api_versions['v3']).to_sql
=> "SELECT \"api_keys\".* FROM \"api_keys\" WHERE \"api_keys\".\"owner_type\" = 'User' AND \"api_keys\".\"api_version\" = 1"
这是 ActiveRecord 中的一个错误,还是它不支持以这种方式查找枚举?我想它会因为枚举的全部意义在于能够使用友好/人类可读的名称。
谢谢!
注意事项
-
ApiKey#api_version列的类型为integer - 我使用的是 Postgres 9.5
- 我正在使用
activerecord-4.2.11.1
跟踪行为
以下是 ActiveRecord 源中发生的情况:
- 在
ActiveRecord::Relation#to_sql()中,它为每个绑定值调用connection.quote(..)(在本例中为User和v3) - 在
ActiveRecord::ConnectionAdapters::Quoting#quote()中,它调用type_cast_for_database()对Integer列进行类型转换 - 在
ActiveRecord::Type::Integer#type_cast_for_database()中,它调用type_cast()来进行实际的类型转换 - 在
ActiveRecord::Type::Value#type_cast()中,它调用cast_value()来进行特定于整数的类型转换 - 在
ActiveRecord::Type::Integer#type_cast_for_database()中调用value.to_i将"v3"(字符串)转换为0(整数)
【问题讨论】:
-
你试过用
:v3代替'v3'吗?文档上的示例使用符号 edgeapi.rubyonrails.org/classes/ActiveRecord/Enum.html 我认为如果你想使用字符串,你必须将{ 'v1' => -1, 'v2' => ... }定义为字符串 -
使用
:v3有类似的问题。它命中同一行 -value.to_i rescue nil- 返回nil并在编译查询中呈现为NULL。 -
不幸的是,将它们定义为
String键也无济于事。结果还是一样。
标签: ruby-on-rails postgresql ruby-on-rails-4 activerecord enums