Ruby on Rails: como adicionar uma restrição não nula a uma coluna existente usando uma migração?

130

No meu aplicativo Rails (3.2), tenho várias tabelas no meu banco de dados, mas esqueci de adicionar algumas restrições não nulas. Pesquisei no Google, mas não consigo encontrar como escrever uma migração que não adicione nulo a uma coluna existente.

TIA.

David Robertson
fonte

Respostas:

93

Para o Rails 4+, a resposta dos nates (usando change_column_null ) é melhor.

Antes do Rails 4, tente change_column .

Dan Wich
fonte
25
Tenha cuidado com essa abordagem - se você tiver outros atributos sobre essa coluna (por exemplo, uma :limitrestrição), precisará repeti-los ao usá-los change_columnou eles serão perdidos. Por esta razão, eu prefiro usarchange_column_null
Nathan Wallace
Observe que isso gera um IrreversibleMigrationque pode não ser o que você deseja.
Nic Nilov
@NicNilov você está falando sobre a resposta OU o comentário de Nathan Wallace?
Mark
@ Mark eu estava falando sobre a resposta, desculpe por não ser específico o suficiente.
Nic Nilov
@NicNilov no dw Eu achava que, embora eu só quisesse checar :) #
Mark #
274

Você também pode usar change_column_null :

change_column_null :table_name, :column_name, false
nates
fonte
8
Resposta mais limpa!
Josh Clique
1
Eu tive que alterá-lo para um monte de colunas e isso não requer a especificação do tipo de coluna para cada coluna, muito melhor!
Dorian
1
Essa é a melhor resposta. No meu banco de dados, eu estava adicionando uma restrição nula em uma coluna com valores nulos preexistentes. change_column não atualizaria esses valores. De acordo com a documentação, change_column_null possui um quarto valor opcional, que é o novo valor para a atualização.
Merovex 01/01
Obrigado por isso. Melhor resposta.
Ryan Rebo 14/03
1
efeito colateral interessante .... reverter a migração definirá o campo para o oposto (falso -> verdadeiro). Portanto, se você criar a migração para vários campos para adicionar uma restrição nula, e alguns campos JÁ tiverem uma restrição nula, em seguida, reverter a migração, REMOVERÁ a restrição nula de qualquer campo que já a tenha.
jpw
10

1) PRIMEIRO: adicione coluna com valor padrão

2) ENTÃO: Remova o valor padrão

add_column :orders, :items, :integer, null: false, default: 0
change_column :orders, :items, :integer, default: nil
rndrfero
fonte
2
esta é a solução correta quando você precisa adicionar uma nova coluna que não seja nula, primeiro defina que ele possui valor padrão, porque o SQLLite irá reclamar (Não é possível adicionar uma coluna NOT NULL com valor padrão NULL) e remova-a!
Milão
2

Se você o estiver usando em um novo script / esquema de migração para criação, veja como podemos defini-lo

class CreateUsers < ActiveRecord::Migration[5.2]
  def change
    create_table :users do |t|
    t.string :name, null: false     # Notice here, NOT NULL definition
    t.string :email, null: false
    t.string :password, null: false
    t.integer :created_by
    t.integer :updated_by 

    t.datetime :created_at
    t.datetime :updated_at, default: -> { 'CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP' }
   end
  end
end
Manjunath Reddy
fonte