为什么ActiveRecord在STI模型的类型列中插入NULL?
我正在从DataMapper移植一个非常大的Rails项目到ActiveRecord。 必须移植的模型中有一组用户模型,它们使用单表继承(STI)来区分一种类型和另一种类型。 以下是它的一个简化版本:
class User < ActiveRecord::Base
...
end
class AdminUser < User
...
end
通常,'type'字段用于通过存储正在保存的对象的类名称(即'AdminUser')来区分用户和AdminUser之间的区别。 它在开发中可以正常工作,但是当我在测试环境中尝试User.create
时,我得到:
ActiveRecord::StatementInvalid: Mysql::Error: Column 'type' cannot be null
ActiveRecord会尝试插入一个新行,将类型列设置为NULL ...可能会导致在测试环境中发生这种情况,但在开发中不会发生这种情况?
事实证明,这是数据库表本身的一个细微差异,导致ActiveRecord的行为发生变化。 测试数据库没有type
列的默认值,而在开发中,默认值是'User'
。 显然,ActiveRecord在为主类类型的对象(从ActiveRecord :: Base继承的类 - 在本例中为User
)插入数据时使用默认值。 为什么它不只是使用类名是超出我的理解!
当我更新我的开发数据库以获得类型列的默认值时(我确实知道它是需要的),我真的很困惑,因为生产数据库已经有了一个,所以我的开发数据库很明显是不同步的。 所以我这样做了:
mysql> ALTER TABLE users MODIFY COLUMN type varchar(50) NOT NULL DEFAULT 'User';
...[ok]
mysql> exit
Bye
$> bundle exec rake db:test:prepare # <-- My Mistake
...[ok]
我以为这就是我所要做的,但事实证明,运行db:test:prepare
只是将您的测试数据库与您的schema.rb
文件相匹配,并且我的schema.rb
文件尚未更新,因此User.create
运行在开发中,但在测试中爆发:D
最后,我开始理解上述所有内容,除此之外,我还需要运行db:migrate
以更新我的schema.rb
文件,然后再运行db:test:prepare
。 一旦我做到了:瞧! User.create
实际上使用了type
列的默认值来插入新的用户对象。
故事的道德启示:
db:schema:load
将它吹走,并用新的开发数据重新开始! (或获得生产转储或其他东西) 使用不同于“type”的列名称
链接地址: http://www.djcxy.com/p/49733.html上一篇: Why is ActiveRecord inserting NULL in the type column of an STI model?
下一篇: ActiveRecord Validation: based on attribute or function