require 'bundler'
Bundler.setup
require 'active_record'
require 'activerecord-import'
ActiveRecord::Base.establish_connection("mysql2://[email protected]/arbug")
ActiveRecord::Base.logger = Logger.new(STDOUT)
# create table posts (id int not null AUTO_INCREMENT, test_at datetime, primary key (id));
class Post < ActiveRecord::Base
end
Post.import((1..10).map{|x| Post.new(test_at: (Time.now-x).strftime("%FT%TZ"))})
このコードは Rails 4.2 では動きます。 Rails 5 では壊れます。 それはなぜか。
このコードによって Rails 4 と 5 で SQL 向けに型変換する処理が違っているからです。
Rails 4 で使われるコードでは
2017-02-20T18:44:00Z
のような文字列を datetime にほおりこむとうまいところ datetime っぽい文字列に変換してくれます。
Rails 5 で使われるコードだと、失敗してます。 この現象を一番シンプルに再現するコードだと
col = Post.columns.select{|x| x.name == "test_at"}.first
caster = ActiveRecord::TypeCaster::Map.new(Post)
caster.type_cast_for_database(col, "2017-02-20T18:44:00Z") #=> "2017-02-20T18:44:00Z"
などとなるかと思います。
この
type_cast_for_database
というのは如何にも内部 API 然としている。
- ActiveRecord::Import がこれを勝手に使っているのがおかしい?
- Rails 5 のバグ
どっちなんだろ、、、