Adicionando: default => true ao booleano na coluna Rails existente


160

Eu já vi algumas perguntas (ou seja, essa ) aqui no SO sobre como adicionar um valor booleano padrão a uma coluna existente. Então tentei a change_columnsugestão, mas não devo estar fazendo certo.

Eu tentei:

$ change_column :profiles, :show_attribute, :boolean, :default => true

Que retorna -bash: change_column: command not found

Eu então corri:

$ rails g change_column :profiles, :show_attribute, :boolean, :default => true

...e

$ rails change_column :profiles, :show_attribute, :boolean, :default => true

Em seguida rake db:migrate, correu , mas o valor para :show_attributepermaneceu nil. Na pergunta mencionada acima, no PostgreSQL, você precisa atualizá-lo manualmente. Como estou usando o PostgreSQL, adicionei o seguinte na minha create_profilesmigração:

t.boolean :show_attribute, :default => true

Alguém pode me dizer o que estou fazendo de errado aqui?

Respostas:


314

change_columné um método de ActiveRecord::Migration, então você não pode chamá-lo assim no console.

Se você deseja adicionar um valor padrão para esta coluna, crie uma nova migração:

rails g migration add_default_value_to_show_attribute

Em seguida, na migração criada:

# That's the more generic way to change a column
def up
  change_column :profiles, :show_attribute, :boolean, default: true
end

def down
  change_column :profiles, :show_attribute, :boolean, default: nil
end

OU uma opção mais específica:

def up
    change_column_default :profiles, :show_attribute, true
end

def down
    change_column_default :profiles, :show_attribute, nil
end

Então corra rake db:migrate.

Não mudará nada para os registros já criados. Para fazer isso, você teria que criar um rake taskou apenas entrar rails consolee atualizar todos os registros (o que eu não recomendaria na produção).

Quando você adicionou t.boolean :show_attribute, :default => trueà create_profilesmigração, espera-se que ela não tenha feito nada. Somente migrações que ainda não foram executadas são executadas. Se você iniciou com um novo banco de dados, ele definiria o padrão como true.


2
Essa chamada change_column deve estar no upmétodo da migração, que é uma nova classe que será gerada em db / migrate /. (O downmétodo deve ser escrito para desfazer o que upfaz.) Faça essa alteração, então rake db:migrate.
Rkb

Ahh, isso faz mais sentido rkb. Obrigado!
tvalent2

que não estava funcionando para mim até que eu escrevi def self.upedef self.down
Kamil Szot

Você provavelmente está usando uma versão mais antiga dos trilhos. Eu acho que essa sintaxe existe desde 3.1.
Robin

E no Rails 5, você deixa o _attribute para que ele diga showou seja qual for o nome da coluna.
labirinto

95

Como variação da resposta aceita, você também pode usar o change_column_defaultmétodo em suas migrações:

def up
  change_column_default :profiles, :show_attribute, true
end

def down
  change_column_default :profiles, :show_attribute, nil
end

Documentos da API do Rails


1
Isso garante que você não vai acidentalmente alterar qualquer uma das outras propriedades da coluna
Brian Low

1
E no Rails 5 você deixa de fora o atributo, por isso deve dizer showou qualquer que seja o nome da coluna.
labirinto

1
@ labyrinth O que você quer dizer? show_attribute é o nome da coluna, acho que o rails 5 não tem nada a ver com isso, certo?
Robin

34

Não tenho certeza de quando isso foi escrito, mas atualmente para adicionar ou remover um padrão de uma coluna em uma migração, você pode usar o seguinte:

change_column_null :products, :name, false

Trilhos 5:

change_column_default :products, :approved, from: true, to: false

http://edgeguides.rubyonrails.org/active_record_migrations.html#changing-columns

Trilhos 4.2:

change_column_default :products, :approved, false

http://guides.rubyonrails.org/v4.2/active_record_migrations.html#changing-columns

Essa é uma maneira pura de evitar procurar nas suas migrações ou esquema as especificações da coluna.


Cuidado, é da documentação do Rails 5. A versão do Rails 4.2 não aceita hash, mas exatamente o novo padrão como terceiro parâmetro. Guides.rubyonrails.org/v4.2/…
Clamoris

Sobre Trilhos 5, fazendo as duas coisas parece ser a maneira mais correta, por exemplo, null: falsee default: :somethingbasicamente
Dorian


1

Se você acabou de fazer uma migração, poderá reverter e fazer sua migração novamente.

Para reverter, você pode executar quantas etapas desejar:

rake db:rollback STEP=1

Ou, se você estiver usando o Rails 5.2 ou mais recente:

rails db:rollback STEP=1

Em seguida, você pode simplesmente fazer a migração novamente:

def change
  add_column :profiles, :show_attribute, :boolean, default: true
end

Não se esqueça de rake db:migratee se você estiver usando herokuheroku run rake db:migrate



0

Se você não deseja criar outro arquivo de migração para uma alteração pequena e recente - no Rails Console:

ActiveRecord::Migration.change_column :profiles, :show_attribute, :boolean, :default => true

Então saia e entre novamente no console do rails, para que as DB-Changes entrem em vigor. Então, se você fizer isso ...

Profile.new()

Você deve ver o valor padrão "show_attribute" como true.

Para registros existentes, se você deseja preservar as configurações "falsas" existentes e atualizar apenas os valores "nil" para seu novo padrão:

Profile.all.each{|profile| profile.update_attributes(:show_attribute => (profile.show_attribute == nil ? true : false))  }

Atualize a migração que criou esta tabela, para que futuras compilações do banco de dados o consigam desde o início. Execute também o mesmo processo em qualquer instância implantada do banco de dados.

Se você estiver usando o método "new db migration", poderá atualizar os valores nulos existentes nessa migração.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.