分享 Active Record Migrations 中设置默认值的一个坑

046569 · 2013年09月29日 · 最后由 Victor 回复于 2013年09月30日 · 3683 次阅读

所有的坑都来自于 无知 ,这次也不例外,我又掉坑里了...

先来看段代码:

def change
  add_column :servers, :vip_date, :date, :default => Date.today
end

这是一个很常见的迁移任务,新增一栏,设置默认值。执行迁移也毫无警告,看起来一切都那么美好。而真相其实是这样的:

假设今天是 9 月 9 日:

Server.new.vip_date  #=> Sun, 09 Sep 2013

嗯,看起来很完美。可过了一天你再试试?

Server.new.vip_date  #=> Sun, 09 Sep 2013

见鬼,怎么还是相同的日期?难道Date.today秀逗了?

表象可能有很多种,而真相只有一个:

Active Record Migrations 并不支持 动态默认值,你应该在回调中处理,比如after_initialize.

你用Time.now来试试看看?

-> { Date.today } 这样?

#3 楼 @windwiny 不支持这个。

#4 楼 @hooopo 这个可能行。用 mysql 的函数。没试过

这个地方是定义数据库结构,应该用数据库相关的函数吧

其实看生成的 schema 就应该理解了吧。

#2 楼 @cym 奇怪,我create_table的时候都是写这个,生成的 seed.rb 文件每次这个字段都更新

#1 楼 @ywjno #3 楼 @windwiny 貌似没用. #4 楼 @hooopo 不明白您的意思,您指的是改用add_column_sql,然后调用 SQL 内置的函数?

用 Active Record 不要脱离了底层数据库的特性。

#8 楼 @ywjno seed.rb 可能每次都重新执行一遍 migration 文件。我猜的。

你一直在执行吧,那肯定第一次执行的时候它的值就已经定死了嘛。

不推荐在数据库层面做默认值的设定。放在 model 里面好吗,亲

。。。这。。。

这个。。。。

#13 楼 @Victor 数据库层做默认值有什么缺点吗?我觉得能在数据库做就在数据库做。

#16 楼 @cym 例如:老大说了,所有产品默认的价格都是 10 元起,放心吧,我们不会卖便宜货,你把数据库的默认值搞成 10 就 ok。

三个月后,现在有个需求,我们以后的东西可能大量上一些低价冲量的产品,能把默认价格调到 1 么?

如果当年你是在数据库层面做的,那你现在要再写一个方法,设置默认值。也就是数据库层面的默认值已经没啥用处了。

#16 楼 @cym 妹子,相信楼上说的吧。。。可能某一天呢不负责数据库维护了,第二天就会被数据库的人骂个半死。

:default => Date.today 不就是 :default => "你当天运行的日期" 吗? 你要数据库层做动态默认值,得用数据自带的函数,而每种数据的函数也是不一样的

migration 这样处理没有问题,如果你要做

http://stackoverflow.com/questions/1580805/how-to-set-the-default-value-for-a-datetime-column-in-migration-script

这跟 Active Record migration 完全没关系

#13 楼 @Victor 亲,我感觉你说的和新建个迁移任务改变默认值并无不同。使用迁移任务的话还可以保持schema清晰完整. #19 楼 @ZombieCoder 你说的方法和我提的有何不同么? #20 楼 @lululau 你觉得问题出在哪,不妨解释下?

rails 的思想,总感觉和传统的 关系型数据库格格不入。所以我喜欢 NoSQL

#22 楼 @suxu 详细说一下?

#22 楼 @suxu 我觉着 Active Record 更好些,统一的语法,让你无需纠结于各数据库的细节. 现在不支持动态的默认值似乎可以认为是当前版本的"缺陷",毕竟在`schema'中看到这样的结构是非常易于理解的

create_table "servers", force: true do |t|
t.date     "vip_date",   default: Date.today
end

#22 楼 @suxu Rails 的基本思想是 convention over configuration. 然后是 Core Team 的成员在框架中选择了他们认为的最好的决定/选择,并且作为默认的。如果你有自己的偏好,可以替换任一个 component,如果你懒得想,那就用默认的。跟是不是关系型,nosql,关系在哪里?

#25 楼 @jun1st 嗯。我喜欢用 rails 是因为它对变化的适应。而关系数据库本身的变化支持是很传统的。个人编好而已,选择什么数据库,关键还是开应用场景。

#21 楼 @046569 当你在一个大团队,维护多个需要设置的默认值。频繁修改的需求(由市场活动,营销策略决定),建立 N 个迁移任务会不会看起来有点乱。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号