Search code examples
ruby-on-railsactiverecordruby-on-rails-6

How to use beginless range in ActiveRecord


Update: This issue has since been fixed in Rails 6.1

I'm getting some inconsistent behavior in Rails 6.0.2.2 when passing beginless and endless ranges to where:

pry(main)> User.where(id: 1..3).ids
   (8.0ms)  SELECT "users"."id" FROM "users" 
    WHERE "users"."id" BETWEEN $1 AND $2 LIMIT $3  [["id", 1], ["id", 3]]
=> [1, 2, 3]

pry(main)> User.where(id: 1..).ids
   (0.5ms)  SELECT "users"."id" FROM "users" 
    WHERE "users"."id" >= $1 LIMIT $2  [["id", 1]]
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

pry(main)> User.where(id: ..3).ids
   (0.4ms)  SELECT "users"."id" FROM "users"
    WHERE "users"."id" BETWEEN $1 AND $2 LIMIT $3 [["id", nil], ["id", 3]]
=> []

When using and endless range inside of where, the generated SQL uses WHERE >= the beginning of the range instead of BETWEEN.

However, when passing a beginless range, it generates a SQL where clause BETWEEN NULL and tne end of the range.

Is this an known issue in ActiveRecord?



Solution

  • It does look like an issue in ActiveRecord and you can get around it by using Arel or Float::INFINITY.

    Client.where(Client.arel_table[:id].gte(id))
    Client.where(id: Float::INFINITY..3)
    

    The issue is solved in Rails 6.1 and is due to be backported to 6.0.