为何Rails/ActiveRecord允许为Date类型列赋值整数?
为何ActiveRecord允许为日期类型列赋值整数?(开发环境使用sqlite3)
数据表结构
create_table "entries", force: :cascade do |t| t.date "date" t.integer "segment" t.integer "user_id", null: false # ... end
控制台测试操作
测试1:赋值整数给date列
执行代码:
e = Entry.new(user_id: 1, segment: 2, date: 42)
得到结果:
#<Entry:0x00000001139b16f8 id: nil, date: 42, segment: 2, user_id: 1, created_at: nil, updated_at: nil> 3.1.2 :065 > e.date.class => Integer
该记录可通过save!成功保存。
测试2:赋值日期字符串给date列
执行代码:
e = Entry.new(user_id: 1, segment: 2, date: "2023-05-06")
得到结果:
#<Entry:0x00000001143d6cf0 id: 1, date: Sat, 06 May 2023, segment: 2, user_id: nil,
此结果符合预期,ActiveRecord会自动将字符串转换为Date类型。
测试3:赋值无效字符串给date列
执行代码:
Entry.new(id: 1, segment: 2, date: "not a date")
得到结果:
#<Entry:0x000000011443e440 id: 1, date: nil, segment: 2, user_id: nil,
此结果也符合预期,无法转换为Date类型时,date字段会被设为nil。
原因分析
- SQLite的动态类型特性:SQLite采用"类型亲和"机制,而非严格的类型强制。声明为
DATE的列,类型亲和性属于NUMERIC,整数属于NUMERIC范畴,因此可以直接存储。 - ActiveRecord的转换规则:ActiveRecord仅会对日期字符串、
Date/Time对象等输入触发日期转换,整数不在默认转换范围内,会被判定为符合列的类型亲和要求,直接保留原值。 - 默认无额外校验:ActiveRecord默认不会对日期列的整数输入做合法性校验(比如判断是否为有效儒略日),除非手动添加模型校验规则(如
validates :date, date: true),否则会直接存储该整数。
内容的提问来源于stack exchange,提问作者Zack
相关产品推荐
相关产品推荐

