前段时间我们将应用程序升级到 Rails 4 并切换到 JRuby。
在此之前,更改迁移将默认时间戳创建为 NOT NULL。更改后,NOT NULL 丢失。
我们按如下方式创建这些时间戳(created_at、updated_at):
class Model < ActiveRecord::Migration
def change
create_table :model do |t|
t.belongs_to :user, :null => false
t.text :content
t.timestamps
end
end
end
我们应用程序的重要部分是:
- Ruby '1.9.3', :engine => '
- jruby', :engine_version => '1.7.9'
- 宝石 "轨道", "4.0.2"
- gem 'activerecord-jdbcpostgresql-adapter', '1.3.4'
- PostgreSQL:稳定版 9.3.1
您是否知道可能导致问题的原因以及我们如何将默认生成更改回 NOT NULL?
它是否记录在任何地方,但来源表明您可以将通常的列选项传递给t.timestamps
:
# Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
# <tt>:updated_at</tt> to the table.
def timestamps(*args)
options = args.extract_options!
column(:created_at, :datetime, options)
column(:updated_at, :datetime, options)
end
所以你可以说:
create_table :model do |t|
#...
t.timestamps :null => false
end
并且您的列不应为 NULL。
如果你看一下3.2版本,你会看到发生了什么:
def timestamps(*args)
options = { :null => false }.merge(args.extract_options!)
#...
end
所以 3.2 默认情况下将时间戳列创建为 NOT NULL,但 4.0 不会。
这个问题激怒了我,因为我有一个旧的应用程序已经在 Rails 3.2 上使用了几年,并且大量使用了此方法,因此这个初始值设定项:
# Force t.timestamps to always be null: false
module ActiveRecord
module ConnectionAdapters
class TableDefinition
def timestamps_with_non_nullable(*args)
options = args.extract_options!
options.merge!(null: false)
timestamps_without_non_nullable(*args, options)
end
alias_method_chain :timestamps, :non_nullable
end
end
end