1

首先,这与我的另一个问题直接相关: 如何在 ActiveRecord 中优雅地处理“Mysql2::Error: Invalid date”?

但是我仍然不想跳过所有编写迁移来确定日期的循环。那不会是最后一个日期无效的表,我需要一些更通用的方法。

所以我们开始:

我正在使用包含无效日期的旧版 MySQL 数据库,有时像 2010-01-00 或 0000-04-25 ... Rails 不会加载此类记录(旧版本的 Rails 会加载)。

我不想(也不能)手动或自动更正这些日期。应该由这些记录的作者来更正这些日期。旧系统是一个允许此类烦恼的 PHP 应用程序。Rails 应用程序应该/将阻止用户在日期有效之前保存记录。

问题似乎不在 Rails 本身,而是在 Rails mysql gem 的 .so 库中更深层次。

所以我的问题不是关于如何验证日期或如何插入无效日期。我不想那样做,这在 stackoverflow 和互联网的其余部分都有很多答案。我的问题是如何从 MySQL 中读取已经存在于数据库中的无效日期,而不会使 Rails 爆炸成 1000 个小块......

列类型是DATETIME,我不确定转换为字符串是否有帮助,因为 Rails 在任何与 ActiveRecord 相关的解析开始之前就会阻塞。

这是确切的错误和回溯:

$导轨c
加载开发环境(Rails 3.2.13)
irb(main):001:0> Poll.first
  轮询负载 (0.5ms) SELECT `polls`.* FROM `polls` LIMIT 1
Mysql2::Error:无效日期:2003-00-01 00:00:00
        来自/home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/connection_adapters/mysql2_adapter.rb:216:in `each'
        来自 /home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/connection_adapters/mysql2_adapter.rb:216:in `to_a'
        来自/home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/connection_adapters/mysql2_adapter.rb:216:in `exec_query'
        来自 /home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/connection_adapters/mysql2_adapter.rb:224:in `select'
        来自/home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/connection_adapters/abstract/database_statements.rb:18:in `select_all'
        来自 /home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/connection_adapters/abstract/query_cache.rb:63:in `select_all'
        来自 /home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/querying.rb:38:in `find_by_sql'
        来自 /home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/explain.rb:41:in `logging_query_plan'
        来自 /home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/querying.rb:37:in `find_by_sql'
        来自/home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/relation.rb:171:in `exec_queries'
        来自 /home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/relation.rb:160:in `to_a'
        来自 /home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/explain.rb:34:in `logging_query_plan'
        来自 /home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/relation.rb:159:in `to_a'
        来自/home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/relation/finder_methods.rb:380:in `find_first'
        来自/home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/relation/finder_methods.rb:122:in `first'
        来自/home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/querying.rb:5:in `__send__'
        来自 /home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/querying.rb:5:in `first'
        来自 (irb):1

即使我这样做,回溯仍然保持不变,Poll.first.title某些日期永远不会到达 IRB 中的任何输出例程,因此永远不应该被解析。因此,在类型转换之前使用值的建议将无济于事。

4

2 回答 2

2

我认为对我有用的最简单的解决方案是在database.yml文件中设置cast: false,例如用于开发部分

development
  <<: *default
  adapter: mysql2    
  (... some other settings ...)
  cast: false
于 2014-12-08T03:09:39.100 回答
0

试试这个

ActiveRecord::AttributeMethods::BeforeTypeCast 提供了一种在类型转换和反序列化之前读取属性值的方法。

http://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/BeforeTypeCast.html

于 2013-08-01T17:04:46.013 回答