首先,这与我的另一个问题直接相关: How to gracefully handle "Mysql2::Error: Invalid date" in ActiveRecord?
但我仍然不想跳过编写修复日期的迁移的所有循环。这不会是无效日期的最后一个表,我需要一些更通用的方法。
所以我们走了:
我正在使用遗留的MySQL数据库,其中包含无效日期,有时像2010-01-00或0000-04-25 ... Rails不会加载此类记录(旧版本的Rails确实如此)。
我不想(也不能)手动或自动更正这些日期。应该由这些记录的作者来纠正这些日期。旧系统是一个允许这种烦恼的PHP应用程序。 Rails应用程序应该/只会阻止用户保存记录,直到日期有效。
问题似乎不在Rails本身内部,而是在rails mysql gem的.so库中更深层次。
所以我的问题不是关于如何验证日期或如何插入无效日期。我不想那样做,而且遍布stackoverflow和互联网的其余部分都有很多答案。我的问题是如何从数据库中已经存在的MySQL中读取无效日期而不将Rails爆炸成1000个小块......
列类型为DATETIME
,我不确定转换为字符串是否有帮助,因为Rails会在任何与ActiveRecord相关的解析开始之前窒息。
这是确切的错误和回溯:
$ rails c Loading development environment (Rails 3.2.13) irb(main):001:0> Poll.first Poll Load (0.5ms) SELECT `polls`.* FROM `polls` LIMIT 1 Mysql2::Error: Invalid date: 2003-00-01 00:00:00 from /home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/connection_adapters/mysql2_adapter.rb:216:in `each' from /home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/connection_adapters/mysql2_adapter.rb:216:in `to_a' from /home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/connection_adapters/mysql2_adapter.rb:216:in `exec_query' from /home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/connection_adapters/mysql2_adapter.rb:224:in `select' from /home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/connection_adapters/abstract/database_statements.rb:18:in `select_all' from /home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/connection_adapters/abstract/query_cache.rb:63:in `select_all' from /home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/querying.rb:38:in `find_by_sql' from /home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/explain.rb:41:in `logging_query_plan' from /home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/querying.rb:37:in `find_by_sql' from /home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/relation.rb:171:in `exec_queries' from /home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/relation.rb:160:in `to_a' from /home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/explain.rb:34:in `logging_query_plan' from /home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/relation.rb:159:in `to_a' from /home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/relation/finder_methods.rb:380:in `find_first' from /home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/relation/finder_methods.rb:122:in `first' from /home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/querying.rb:5:in `__send__' from /home/kakra/.gem/ruby/1.8/gems/activerecord-3.2.13/lib/active_record/querying.rb:5:in `first' from (irb):1
即使我执行Poll.first.title
,回溯仍保持不变,因此某些日期永远不会到达IRB中的任何输出例程,因此永远不应该被解析。因此,在类型转换之前使用值的建议无济于事。
答案 0 :(得分:2)
我认为对我有用的最简单的解决方案是设置 database.yml 文件 cast:false ,例如发展部分
development
<<: *default
adapter: mysql2
(... some other settings ...)
cast: false
答案 1 :(得分:0)
试试这个
ActiveRecord :: AttributeMethods :: BeforeTypeCast提供了一种在类型转换和反序列化之前读取属性值的方法。
http://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/BeforeTypeCast.html