【问题标题】:Type Casting a Column to bigint in Padrino Active Record在 Padrino Active Record 中键入将列转换为 bigint
【发布时间】:2017-07-04 20:41:01
【问题描述】:

我已在 Padrino 应用程序上升级到最新的 Ruby,并且在创建新对象时出现活动记录错误。它将一个数字(ISBN)验证为 4 个字节。错误是:

9781407005416 is out of range for ActiveRecord::Type::Integer with limit 4

如何告诉 Ruby 活动记录类使用 8 字节限制?

我不是在谈论运行迁移,表已经是bigint(20)

我认为以下方法会起作用:

class Book < ActiveRecord::Base
    attribute :isbn, :integer, :limit => 8
end

然后,我在 ISBN 字段的 find_byas_json 上收到错误:

#&lt;NoMethodError: undefined method 'type_cast_for_database' for :integer:Symbol

我将“isbn”方法变成了一个新的实例变量,而不是更改活动记录适配器创建的属性列。

我知道column has a limit,但不确定如何访问列的类型来更新它。

类型设置的解决方案是有一种方法可以跳过活动记录ensure_in_range中现在发生的验证。

有没有办法从我的应用程序中更改内置的 DEFAULT_LIMIT = 4class Integer &lt; Value?这与following changes in Ruby 有关,但我无权更改Padrino 源。

【问题讨论】:

  • 你用的是什么数据库?
  • MySQL,ruby 适配器未捕获大整数并相应调整限制。

标签: ruby rails-activerecord padrino


【解决方案1】:

如何告诉 Ruby 活动记录类使用 8 字节限制? AFAIK,AR 应该直接从数据库元数据中解决这个问题。

首先,如果尚未完成,请重新启动应用程序 - 列类型已缓存。接下来,我将验证 AR 是否确实按照您的预期看到了该列。试试这个以确保它按照你的想法做:

p Book.columns.select{ |col| col.name == 'isbn'}

查看@cast_type 下的@range 和@limit。

我将“isbn”方法变成了一个新的实例变量,而不是 更改由活动记录创建的属性的列 适配器。

这是否意味着您覆盖了 isbn getter?如果是这样,该代码到底是什么样的?

【讨论】:

  • @Conor - 很高兴为您提供帮助。 "p Book.columns.select{ |col| col.name == 'isbn'}" 的结果是什么?我在 Rails 4.2.8 上使用 mysql2 驱动程序 (mysql2-0.4.5) 对此进行了测试,它正确地将字段解释为 bigint 并处理您上面的值。您引用的帖子是关于 sqllite 的,它对此有问题,可能需要“attribute :upc, Type ...” hack,但 MySQL 不应该。由于这是一个内部 API,因此应该避免恕我直言。您是否有机会使用 mysql1 驱动程序或旧的 mysql2 驱动程序?
  • 我很想避免它,但无论如何都会出错。似乎问题更严重,因为输出正确 "[#<:connectionadapters::abstractmysqladapter::column:0x007fbb930f95a0 cast_type="#<ActiveRecord::Type::Integer:0x007fbb92d01c40">, @sql_type="bigint(20)", @空=真,@default=nil,@default_function=nil>]"。使用 mysql2 0.4.7,但不使用 Rails、Sinatra 2.0.0 和 padrino 0.14.1.1。
  • 适时摆脱 protected_attributes gem,让您知道会发生什么。
  • 通过带有活动记录 5.1.2 的测试,将部署它并查看它是如何上线的。
  • @Conor,查看Padrino的源代码,它依赖于sequel,而sequel又需要activerecord。看起来续集在其上堆叠了 lot ,所以我怀疑错误存在于其中的某个地方。如果是这种情况,我们可能不得不采用您的第一种方法(属性:isbn,:integer ...)。
【解决方案2】:

试试:

validates_inclusion_of :isbn, in: 1..4294967296

(即2^32,即最大4字节整数。)

或者8个字节,试试:

validates_inclusion_of :isbn, in: 1..1.8446744e+19

确认这个非常大的范围是有效的:

> 1e10.in?(1..1.8446744e+19)
true
> 1e20.in?(1..1.8446744e+19)
false

(我假设 Padrino 的 AR 像 Rails 一样工作。)

【讨论】:

  • 感谢您的建议。不幸的是,验证是在字节限制检查之上添加的,因此它不会覆盖 4 字节的默认限制。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-23
  • 1970-01-01
  • 2013-06-17
  • 2014-03-05
相关资源
最近更新 更多