RangeError when querying for big number using #where in Rails 4.2
Asked Answered
A

1

6

I've just upgraded an old app from Rails 3.0 to 4.2 and now it is impossible to query the database for very long IDs.

Rails 3

Product.where(associated_id: 1311344470881970878875083923).first
=> nil

Rails 4.2.3

Product.where(associated_id: 1311344470881970878875083923).first
RangeError: 1311344470881970878875083923 is out of range for ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Integer with limit 8
from ~/.rvm/gems/ruby-2.2.1@gemset/gems/activerecord-4.2.3/lib/active_record/type/integer.rb:45:in `ensure_in_range'

I'd expect that the finder returns nothing in Rails 4.2.3 as well in such a case. It's just searching for results, we don't need to call ensure_in_range.

UPDATE: however, the following works fine (it may serve as a workaround):

Product.find_by(associated_id: 1311344470881970878875083923)

It works because find_by is implemented as below:

def find_by(*args)
  where(*args).take
rescue RangeError
  nil
end

http://api.rubyonrails.org/classes/ActiveRecord/FinderMethods.html#method-i-find_by

Unfortunately a similar method for returning all results is missing in ActiveRecord 4.2.3

def find_all_by(*args)
  where(*args).load
rescue RangeError
  none
end
Affection answered 20/8, 2015 at 11:24 Comment(1)
thats a pretty big number for an integer!Groundsel
G
-1

1311344470881970878875083923 ist way out of the INT Range in postgres. Every Datatype has its own range. a Integer normally presenting 4 bytes, which means there are 4294967294 different values. (-2147483647 till +2147483647 and a 0).

if you need those big numbers as the object_id, make sure to use a bigint. he can handle those.

http://www.postgresql.org/docs/9.3/static/datatype-numeric.html

edit

as on your edit, you can extend your ActiveRecord with ease

# config/initializer/active_record.rb

class ActiveRecord::Base     
  def self.find_all_by(*args)
      where(*args).load
    rescue RangeError
      nil
  end
end
Groundsel answered 20/8, 2015 at 11:58 Comment(3)
This really doesn't bring anything to this discussion. See the "UPDATE" section in my first post. What we're really missing is something like find_all_by . It doesn't matter what kind of number I'm sending to this query, it should not fail with such an error when I just want to find something in the database.Affection
so why dont you implement your own "find_all" method?Groundsel
Of course I can extend AR with my method. I was looking for some hints about implementing it using unmodified AR.Affection

© 2022 - 2024 — McMap. All rights reserved.