如何检查一个数字是否在activerecord中的范围内?

Bri*_*Law 0 postgresql activerecord ruby-on-rails

我有一个带有范围列的模型

#<JobRequirement id: 1, age: 18...30>
Run Code Online (Sandbox Code Playgroud)

我怎样才能JobRequirement使用age: 20

就像是

JobRequirement.where(age: 20)
Run Code Online (Sandbox Code Playgroud)

mu *_*ort 5

我认为你需要在字符串中使用PostgreSQL 范围运算符和一些 SQL。特别是,您需要@>(包含元素) 运算符:

JobRequirement.where('age @> ?', 20)
Run Code Online (Sandbox Code Playgroud)

至于提供一个范围作为占位符值:

JobRequirement.where('age <@ ?', 18..20)
Run Code Online (Sandbox Code Playgroud)

你会发现 AR 对 PostgreSQL 范围类型的了解有些有限。当您提供一个范围作为占位符的值时,AR 会希望将该范围扩展到逗号分隔的列表,因为它假设您说的是这样的内容,where('col in (?)', 18..20)因此您最终会得到如下废话:

where age <@ 18,19,20
Run Code Online (Sandbox Code Playgroud)

在生成的 SQL 中。您可以通过手动类型转换值来解决此问题;例如:

> ActiveRecord::Base.connection.type_cast(6..11)
 => "[6,11]" 
> ActiveRecord::Base.connection.type_cast(6...11)
 => "[6,11)" 
Run Code Online (Sandbox Code Playgroud)

然后将字符串发送到查询中,PostgreSQL 会自动将其转换为 PostgreSQL 范围:

JobRequirement.where('age <@ ?', ActiveRecord::Base.connection.type_cast(18..20))
Run Code Online (Sandbox Code Playgroud)

根据您执行此操作的位置,该connection方法可能适用于所有噪音:

JobRequirement.where('age <@ ?', connection.type_cast(18..20))
Run Code Online (Sandbox Code Playgroud)

如果 PostgreSQL 没有<@自行选择正确版本的运算符,那么您可以帮助它进行更多类型转换:

JobRequirement.where('age <@ ?::int4range', connection.type_cast(18..20))
Run Code Online (Sandbox Code Playgroud)