Renombrar tabla en rieles

154

Quiero cambiar el nombre de una tabla ... (cualquier tabla).

Probé esta línea de código:

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

Aquí está lo raro. Sé que lo hice funcionar la primera vez, pero ahora recibo este error: método indefinido `rename_table 'para ActiveRecord :: ConnectionAdapters :: SchemaStatements: Module

¿Había algo que necesito configurar?

Tommy
fuente

Respuestas:

248

Normalmente haría este tipo de cosas en una migración:

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

  def self.down
    rename_table :bar, :foo
  end
end
leva
fuente
1
Gracias que funcionó! Todavía estoy desconcertado por qué la línea anterior no lo hizo. Oh bien ..
Tommy
@Tommy, el rename_tablemétodo se define en el ActiveRecord::ConnectionAdapters::SchemaStatements. Está destinado a ser mezclado con otros módulos. Si quisieras ejecutarlo directamente, creo que podrías hacerloinclude ActiveRecord::ConnectionAdapters::SchemaStatements; rename_table :foo, :bar
cam
o puede usar ActiveRecord :: Migration.rename_table (: foo,: bar) si así lo desea. Pero la migración funciona mejor. ¿También le gustaría cambiar el nombre del modelo o desea conservar el nombre del modelo como el anterior? Si es así, es posible que desee especificar el nombre de la tabla en el modelo ActiveRecord usando "set_table_name: bar".
Aditya Sanghi
1
También puede usar el nuevo formulario para migraciones con el método 'cambiar' en lugar de arriba y abajo. ejemplo
MegaTux el
cambio de def, no def self.up / def.self.down en implementaciones modernas de Rails. Hacer esto último fallará en silencio.
huertanix
294

Recuerda que en Rails> = 3.1 puedes usar el changemétodo.

 class RenameOldTableToNewTable < ActiveRecord::Migration
   def change
     rename_table :old_table_name, :new_table_name
   end 
 end
Mikhail Grishko
fuente
37
Esto también migrará cualquier índice de :old_table_namea:new_table_name
Gavin Miller el
77
Solo un pequeño comentario: tal vez cambie a: old_named_things,: new_named_things para recordar a las personas que los nombres de las tablas en activerecord generalmente están en plural.
Carpela
24

.rename_tablees un método de instancia, no un método de clase, por lo que llamar Class.methodno va a funcionar. En su lugar, tendrá que crear una instancia de la clase, y llame al método en la instancia, así: Class.new.method.

[EDITAR] En esta instancia, ActiveRecord::ConnectionAdapters::SchemaStatementsni siquiera es una clase (como lo señaló la cámara), lo que significa que ni siquiera puedes crear una instancia de ella según lo que dije anteriormente. E incluso si usaras el ejemplo de cam class Foo; include ActiveRecord::ConnectionAdapters::SchemaStatements; def bar; rename_table; end; end;, todavía no funcionaría, ya que rename_tableplantea una excepción.

Por otro lado, ActiveRecord::ConnectionAdapters::MysqlAdapter es una clase, y es probable que tenga que usar esta clase para cambiar el nombre de su tabla (o SQLite o PostgreSQL, dependiendo de la base de datos que esté usando). Ahora, como sucede, ActiveRecord::ConnectionAdapters::MysqlAdapterya se puede acceder a él Model.connection, por lo que debería poder hacerlo completamente Model.connection.rename_table, utilizando cualquier modelo en su aplicación. [/EDITAR]

Sin embargo, si desea cambiar el nombre de una tabla de forma permanente, le sugiero que utilice una migración para hacerlo. Es fácil y la forma preferida de manipular la estructura de su base de datos con Rails. Aquí se explica cómo hacerlo:

# 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

Luego, puede ejecutar su migración con rake db:migrate(que llama al self.upmétodo) y usar rake db:rollback(qué llamadas self.down) para deshacer la migración.

vonconrad
fuente
Estoy de acuerdo en que rename_tablees un método de instancia, pero no está definido en una clase, por lo que su sugerencia para llamar Class.new.methodno funcionará (por ejemplo: ActiveRecord::ConnectionAdapters::SchemaStatements.newda el oMethodError: undefined method nuevo error 'para ActiveRecord :: ConnectionAdapters :: SchemaStatements: Module`
cam
1
También vale la pena señalar que si tiene un modelo asociado con la tabla, está cambiando el nombre, ejecutando rake db:migrateo rake db:rollbackno cambiará el nombre del archivo model.rb. Deberá cambiar manualmente el archivo model.rb.
9monkeys
1
En las versiones más recientes de Rails (por ejemplo, 5.x), puede usar un método de cambio en lugar de self.up y self.down , porque Rails también puede realizar una reversión por esto. Por lo que sólo este código es suficiente: def change rename_table :my_table, :my_new_table end. . . . . Por cierto: Dentro de changeque el uso de estos comandos: add_column, add_index, add_timestamps, create_table, remove_timestamps, rename_column, rename_index,rename_table
Belleza
2
ActiveRecord::Migration.rename_table(:old_table_name, :new_table_name)
imsinu9
fuente