Renomeando tabela em trilhos

154

Quero renomear uma tabela ... (qualquer tabela).

Eu tentei esta linha de código:

ActiveRecord::ConnectionAdapters::SchemaStatements.rename_table(old_name, new_name)

Aqui está a coisa estranha. Sei que o fiz funcionar pela primeira vez, mas agora recebo este erro: método indefinido `rename_table 'para ActiveRecord :: ConnectionAdapters :: SchemaStatements: Module

Havia algo que eu precisava definir?

Tommy
fonte

Respostas:

248

Você normalmente faria esse tipo de coisa em uma migração:

class RenameFoo < ActiveRecord::Migration
  def self.up
    rename_table :foo, :bar
  end

  def self.down
    rename_table :bar, :foo
  end
end
cam
fonte
1
Obrigado que funcionou! Ainda estou confuso por que a linha anterior não o fez. Oh bem ..
Tommy
@ Tommy, o rename_tablemétodo é definido no ActiveRecord::ConnectionAdapters::SchemaStatements. Ele deve ser misturado a outros módulos. Se você queria executá-lo diretamente, eu acho que você poderia fazerinclude ActiveRecord::ConnectionAdapters::SchemaStatements; rename_table :foo, :bar
cam
ou você pode usar o ActiveRecord :: Migration.rename_table (: foo,: bar) se assim o desejar. Mas a migração funciona melhor. Você também deseja alterar o nome do modelo ou manter o nome do modelo como o antigo? Nesse caso, convém especificar o nome da tabela no modelo ActiveRecord usando "set_table_name: bar".
Aditya Sanghi
1
Você também pode usar o novo formulário para migrações com o método 'change' em vez de subir e descer. exemplo
MegaTux 6/12/11
def change, não def self.up / def.self.down nas implementações modernas do Rails. Fazer o último falhará silenciosamente.
precisa saber é o seguinte
294

Lembre-se de que no Rails> = 3.1 você pode usar o changemétodo

 class RenameOldTableToNewTable < ActiveRecord::Migration
   def change
     rename_table :old_table_name, :new_table_name
   end 
 end
Mikhail Grishko
fonte
37
Isso também migrará todos os índices de :old_table_namepara:new_table_name
Gavin Miller
7
Apenas um pequeno comentário: Talvez mude para: old_named_things,: new_named_things para lembrar às pessoas que os nomes das tabelas no registro de atos geralmente são pluralizados.
Carpela 20/09/17
24

.rename_tableé um método de instância, não um método de classe, portanto, a chamada Class.methodnão vai funcionar. Em vez disso, você precisará criar uma instância da classe e chamar o método na instância, assim:Class.new.method .

[EDIT] Nesse caso, ActiveRecord::ConnectionAdapters::SchemaStatementsnem sequer é uma classe (como apontado por cam), o que significa que você não pode nem mesmo criar uma instância dela conforme o que eu disse acima. E mesmo se você usou o exemplo de cam class Foo; include ActiveRecord::ConnectionAdapters::SchemaStatements; def bar; rename_table; end; end;, ele ainda não funcionaria comorename_table uma exceção.

Por outro lado, ActiveRecord::ConnectionAdapters::MysqlAdapter é uma classe e é provável que você precise renomear sua tabela (ou SQLite ou PostgreSQL, dependendo do banco de dados que você está usando). Agora, por acaso, ActiveRecord::ConnectionAdapters::MysqlAdapterjá está acessível Model.connection, então você deve poder fazer isso completamenteModel.connection.rename_table usando qualquer modelo em seu aplicativo. [/EDITAR]

No entanto, se você deseja renomear permanentemente uma tabela, sugiro usar uma migração para fazê-lo. É fácil e a maneira preferida de manipular sua estrutura de banco de dados com o Rails. Veja como fazê-lo:

# Commandline
rails generate migration rename_my_table

# In db/migrate/[timestamp]_rename_my_table.rb:
class RenameMyTable < ActiveRecord::Migration
  def self.up
    rename_table :my_table, :my_new_table
  end

  def self.down
    rename_table :my_new_table, :my_table
  end
end

Em seguida, você pode executar sua migração com rake db:migrate(que chama o self.upmétodo) e usar rake db:rollback(quais chamadas self.down) para desfazer a migração.

vonconrad
fonte
Concordo que rename_tableé um método de instância, mas não está definido em uma classe, portanto sua sugestão de chamada Class.new.methodnão funcionará (por exemplo: ActiveRecord::ConnectionAdapters::SchemaStatements.newfornece o erro oMethodError: undefined method novo 'para ActiveRecord :: ConnectionAdapters :: SchemaStatements: Module`
cam
1
Também vale ressaltar que, se você tiver um modelo associado à tabela, está renomeando, executando rake db:migrateou rake db:rollbacknão renomeará o arquivo model.rb. Você precisará alterar manualmente o arquivo model.rb.
9monkeys
1
Nas versões mais recentes do Rails (por exemplo, 5.x), você pode usar um método de mudança em vez de self.up e self.down , porque o Rails também pode executar uma reversão por isso. Então, só este código é suficiente: def change rename_table :my_table, :my_new_table end. . . . . Pela maneira: Dentro de changevocê um usar esses comandos: add_column, add_index, add_timestamps, create_table, remove_timestamps, rename_column, rename_index,rename_table
Beauty
2
ActiveRecord::Migration.rename_table(:old_table_name, :new_table_name)
imsinu9
fonte