Перенос Rails генерирует временные метки по умолчанию (created_at, updated_at) как NULLABLE

Некоторое время назад мы обновили наше приложение до 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'
  • gem 'rails', '4.0.2'
  • gem 'activerecord-jdbcpostgresql-adapter', '1.3.4'
  • postgresql: stable 9.3.1

Есть ли у вас какая-либо идея, что может вызвать проблему, и как мы можем изменить генерацию по умолчанию на NOT NULL?

Ответ 1

Я не знаю, где он документирован, но источник указывает, что вы можете передать обычные параметры столбца в 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

а ваши столбцы должны быть NOT NULL.

Если вы посмотрите на 3.2 версию, вы увидите, что произошло:

def timestamps(*args)
  options = { :null => false }.merge(args.extract_options!)
  #...
end

поэтому 3.2 создает столбцы временной метки как NOT NULL по умолчанию, но 4.0 не делает.

Ответ 2

Этот вопрос вызвал ярость из-за того, что у меня было старое приложение, которое было на 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