Cast Rails范围为Postgres系列

时间:2014-06-20 08:46:03

标签: ruby-on-rails postgresql range

我想知道在DB中查找行时是否可以强制Rails将范围转换为postgres范围 我的数据库中有一个表,日期范围列类型为

 create_table "events", force: true do |t|
   ......
    t.daterange "date"

  end

当我插入新行时,Rails知道如何转换范围 E.g

Event.create date: Date.today..Date.tomorrow 

按预期工作,我在'事件'日期值等于' [2014-07-16,2014-07-17)'

的表格

但是当我尝试使用to_formatted(:db)方法从db Rails转换范围中选择行时 所以

range = Date.today..Date.tomorrow
Event.find_by date:range

变成

SELECT  "events".* FROM "events"  WHERE ("events"."date" BETWEEN 2014-07-16 AND 2014-07-17) LIMIT 1

我希望得到的是

SELECT  "events".* FROM "events"  WHERE ("events"."date" [2014-07-16, 2014-07-17) LIMIT 1

我通过向RANGE_FORMATS添加新的格式化程序扩展了核心Range类

现在使用

Event.find_by date:range.to_s(:pg)

有更有效的方法来解决问题吗?

2 个答案:

答案 0 :(得分:2)

我知道这是一个2岁的问题,但我遇到了类似的问题并且认为我分享了我的解决方法。

我在ActiveRecord模型中定义了范围:

scope :score_range, ->(score_range) {
    where('course_placement_rubrics.score_range @> numrange(?)', score_range)
}

我这样称呼这个范围:

CoursePlacementRubric.score_range( (0..5.0)  )

ActiveRecord构建了以下查询:

SELECT "course_placement_rubrics".*
FROM "course_placement_rubrics"
WHERE (course_placement_rubrics.score_range @> numrange(0,1,2,3,4,5))

ActiveRecord尝试提供帮助并迭代我的范围。在您的情况下,ActiveRecord尝试提供帮助并使用BETWEEN..AND谓词。这显然不是我和你想要的。

这是我的简单解决方法:

scope :score_range, ->(score_range) {
    where('course_placement_rubrics.score_range @> numrange(?, ?)', score_range.first, score_range.last)
}

这会输出我想要的查询:

SELECT "course_placement_rubrics".*
FROM "course_placement_rubrics"
WHERE (course_placement_rubrics.score_range @> numrange(0, 5))

希望这有助于某人。

答案 1 :(得分:1)

这是AR的默认行为。如果您在AR来源中看到:

https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation/predicate_builder.rb#L112

这是Arel in方法:

https://github.com/rails/arel/blob/master/lib/arel/predications.rb#L27

因此,如果您想拥有更漂亮的代码,则需要覆盖此in方法。