Rails 4.2.0 中简单整数赋值的 RangeError 应该被验证捕获

RangeError for simple integer assignment in Rails 4.2.0 that should be caught by validation

* 更新:现在已在 4.2.stable 和 4.2.1 *

中修复

在 Rails 4.2.0(和当前的 4.2.stable)中,ensure_in_range 方法发生在 AR 验证之前,产生 RangeError

如果我做一些像

这样简单的事情
@obj.threshold = 10_000_000_000

在具有 postgres 类型整数的列上

 threshold  | integer                     | 

它产生

RangeError: 10000000000 is out of range for ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Integer with limit 4 from .../2.0.0-p598/lib/ruby/gems/2.0.0/bundler/gems/rails-62e9e61f2d1b/activerecord/lib/active_record/type/integer.rb:41:in `ensure_in_range'

这是真的!但告诉用户。有一个像

这样的 ActiveRecord 模型验证
  validates :threshold,  presence: true,
    numericality: { greater_than_or_equal_to: 0, less_than: 1_000_000}

我无法想象这是预期的行为,有人可以解释为什么这种类型转换发生在验证之前吗?

获取最新的 rails 版本以修复此错误,it was recently fixed by Sean Griffin

要在版本发布之前执行此操作,请删除您的 gemfile 中的特定版本并使用 git 位置提示:

gem 'rails', :git => 'https://github.com/rails/rails.git'

如果您只有一个验证,那么升级到 Rails 4.2.1 就可以了。但是,如果您有多个验证,例如还要验证唯一性,则必须升级到比 4.2.1 更新的版本。我升级到 4.2.3。不知道4.2.2能不能用

在我的例子中,这也发生在简单的 where(some_id: BIG_NUMBER_HERE) 上。我不会按预期描述它,这应该导致 ActiveRecord::RecordNotFound

您可以强制迁移文件使用 BigInt。我有同样的问题,但我没有使用 Rails 而只是 ActiveRecord。这将解决您的错误:

t.integer :really_big_int, limit: 8