¿Cómo puedo cambiar el nombre de una columna de la base de datos en una migración de Ruby on Rails?


Nombré erróneamente una columna hased_password en lugar de hashed_password.

¿Cómo actualizo el esquema de la base de datos, usando migración para cambiar el nombre de esta columna?

Author: Peter Mortensen, 2010-01-02

25 answers

rename_column :table, :old_column, :new_column

Actualización:

Probablemente quieras crear una migración separada para hacer esto. (Cambia el nombre de FixColumnName como quieras)

script/generate migration FixColumnName
# creates  db/migrate/xxxxxxxxxx_fix_column_name.rb

Luego edita la migración para hacer tu voluntad.

# db/migrate/xxxxxxxxxx_fix_column_name.rb
class FixColumnName < ActiveRecord::Migration
  def self.up
    rename_column :table_name, :old_column, :new_column
  end

  def self.down
    # rename back if you need or do something else or do nothing
  end
end

Una actualización para Rails 3.1

Mientras que, los métodos up y down siguen siendo aplicables. Rails 3.1 recibe un método change que " sabe cómo migrar su base de datos y revertirla cuando la migración se revierte sin la necesidad de escribir un método descendente separado "

rails g migration FixColumnName

class FixColumnName < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end

Si tiene un montón de columnas para cambiar el nombre, o algo que habría requerido repetir el nombre de la tabla una y otra vez.

rename_column :table_name, :old_column1, :new_column1
rename_column :table_name, :old_column2, :new_column2
...

Podrías usar change_table para mantener las cosas un poco más ordenadas.

class FixColumnNames < ActiveRecord::Migration
  def change
    change_table :table_name do |t|
      t.rename :old_column1, :new_column1
      t.rename :old_column2, :new_column2
      ...
    end
  end
end

Gracias, Luke && Turadg, por sacar el tema.

Entonces solo db:migrate como de costumbre o como quiera que vaya con sus negocios.


Una actualización para Rails 4

Al crear un Migration para cambiar el nombre de una columna, Rails 4 genera un método change en lugar de up y down como se mencionó en la respuesta anterior. El método generado change es el siguiente:

$ > rails g migration ChangeColumnName

Que creará un archivo de migración similar a este :

class ChangeColumnName < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end
 2115
Author: nowk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-04 19:18:33

IMO, en este caso, mejor uso rake db:rollback. A continuación, edite su migración y vuelva a escribir rake db:migrate. Sin embargo, si tiene datos en la columna que no desea perder, use rename_column.

 66
Author: elf.xf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-03 21:51:09

Http://api.rubyonrails.org/classes/ActiveRecord/Migration.html

Bajo Available Transformations

rename_column(table_name, column_name, new_column_name):

Cambia el nombre de una columna pero mantiene el tipo y el contenido.

 26
Author: James Manning,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-07 11:34:54

Si la columna ya está poblada con datos y vive en producción, recomendaría un enfoque paso a paso, para evitar el tiempo de inactividad en producción mientras espera las migraciones.

Primero crearía una migración de base de datos para agregar columnas con el(los) nuevo (s) nombre (s) y rellenarlas con los valores del antiguo nombre de columna.

class AddCorrectColumnNames < ActiveRecord::Migration
  def up
    add_column :table, :correct_name_column_one, :string
    add_column :table, :correct_name_column_two, :string

    puts 'Updating correctly named columns'
    execute "UPDATE table_name SET correct_name_column_one = old_name_column_one, correct_name_column_two = old_name_column_two"
    end
  end

  def down
    remove_column :table, :correct_name_column_one
    remove_column :table, :correct_name_column_two
  end
end

Entonces confirmaría solo ese cambio, y empujaría el cambio a producción.

git commit -m 'adding columns with correct name'

Entonces, una vez que el commit ha sido empujado a la producción, yo ejecutar.

Production $ bundle exec rake db:migrate

Luego actualizaría todas las vistas/controladores que hacían referencia al antiguo nombre de columna al nuevo nombre de columna. Ejecutar a través de mi conjunto de pruebas, y confirmar solo esos cambios. (Después de asegurarse de que estaba trabajando localmente y pasar todas las pruebas primero!)

git commit -m 'using correct column name instead of old stinky bad column name'

Entonces yo empujaría ese compromiso a la producción.

En este punto, puede eliminar la columna original sin preocuparse por ningún tipo de tiempo de inactividad asociado con la migración en sí.

class RemoveBadColumnNames < ActiveRecord::Migration
  def up
    remove_column :table, :old_name_column_one
    remove_column :table, :old_name_column_two
  end

  def down
    add_column :table, :old_name_column_one, :string
    add_column :table, :old_name_column_two, :string
  end
end

Luego presione esto última migración a producción y ejecutar bundle exec rake db:migrate en segundo plano.

Me doy cuenta de que esto está un poco más involucrado en un proceso, pero prefiero hacer esto que tener problemas con mi migración de producción.

 24
Author: Paul Pettengill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-14 02:01:38

Ejecute el siguiente comando para crear un archivo de migración:

rails g migration ChangeHasedPasswordToHashedPassword

Luego, en el archivo generado en la carpeta db/migrate, escriba rename_column de la siguiente manera:

class ChangeOldCoulmnToNewColumn < ActiveRecord::Migration
  def change
     rename_column :table_name, :hased_password, :hashed_password
  end
end
 16
Author: Shoaib Malik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-03 21:56:42

De API:

rename_column(table_name, column_name, new_column_name)

Cambia el nombre de una columna pero mantiene el tipo y el contenido sigue siendo el mismo.

 13
Author: super_p,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-10 13:01:24

Algunas versiones de Ruby on Rails soportan el método up / down a la migración y si tienes el método up/down en tu migración, entonces:

def up
    rename_column :table_name, :column_old_name, :column_new_name
end

def down
    rename_column :table_name, :column_new_name, :column_old_name
end

Si tiene el método change en su migración, entonces:

def change
    rename_column :table_name, :column_old_name, :column_new_name
end

Para más información puede mover: Ruby on Rails - Migraciones o Registro Activo de las Migraciones.

 12
Author: uma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-03 21:54:00

Si su código no se comparte con otro, entonces la mejor opción es hacer solo rake db:rollback a continuación, edite el nombre de su columna en migración y rake db:migrate. Eso es todo

Y puede escribir otra migración para cambiar el nombre de la columna

 def change
    rename_column :table_name, :old_name, :new_name
  end

Eso es todo.

 10
Author: sunil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-04 14:34:30

Si necesita cambiar los nombres de las columnas, deberá crear un marcador de posición para evitar un error de nombre de columna duplicado. He aquí un ejemplo:

class SwitchColumns < ActiveRecord::Migration
  def change
    rename_column :column_name, :x, :holder
    rename_column :column_name, :y, :x
    rename_column :column_name, :holder, :y
  end
end
 8
Author: Abram,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-09 14:25:51

Como opción alternativa, si no estás casado con la idea de las migraciones, hay una gema atractiva para ActiveRecord que manejará los cambios de nombre automáticamente por ti, estilo Datamapper. Todo lo que hace es cambiar el nombre de la columna en su modelo (y asegúrese de poner Modelo.auto_upgrade! en la parte inferior de su modelo.rb) y viola! La base de datos se actualiza sobre la marcha.

Https://github.com/DAddYE/mini_record

Nota: Usted tendrá que nuke db/schema.rb para prevenir conflictos

Todavía en fases beta y obviamente no para todos, pero sigue siendo una opción convincente (actualmente lo estoy usando en dos aplicaciones de producción no triviales sin problemas)

 7
Author: Steven Garcia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-12 13:57:26

Si los datos actuales no son importantes para usted, simplemente puede eliminar su migración original utilizando:

rake db:migrate:down VERSION='YOUR MIGRATION FILE VERSION HERE'

Sin las comillas, luego realice cambios en la migración original y ejecute la migración ascendente de nuevo:

rake db:migrate
 6
Author: dirtydexter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-03 21:51:47

Simplemente cree una nueva migración, y en un bloque, use rename_column como se muestra a continuación.

rename_column :your_table_name, :hased_password, :hashed_password
 6
Author: jon snow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-03 21:55:06

Para Ruby on Rails 4:

def change
    rename_column :table_name, :column_name_old, :column_name_new
end
 6
Author: Hardik Hardiya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-03 21:57:01

Manualmente podemos usar el siguiente método:

Podemos editar la migración manualmente como:

  • Abierto app/db/migrate/xxxxxxxxx_migration_file.rb

  • Actualizar hased_password a hashed_password

  • Ejecute el siguiente comando

    $> rake db:migrate:down VERSION=xxxxxxxxx
    

Entonces eliminará su migración:

$> rake db:migrate:up VERSION=xxxxxxxxx

Agregará su migración con el cambio actualizado.

 5
Author: Sumit Munot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-03 21:56:04

Generar el archivo de migración:

rails g migration FixName

# Crea db / migrate / xxxxxxxxxx.rb

Edite la migración para hacer su voluntad.

class FixName < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end
 4
Author: vipin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-03 21:59:36
$:  rails g migration RenameHashedPasswordColumn
invoke  active_record
      create    db/migrate/20160323054656_rename_hashed_password_column.rb

Abra ese archivo de migración y modifique ese archivo como se muestra a continuación(Ingrese su original table_name)

class  RenameHashedPasswordColumn < ActiveRecord::Migration
  def change
    rename_column :table_name, :hased_password, :hashed_password
  end
end
 4
Author: Prabhakar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-23 05:49:28

Ejecuta rails g migration ChangesNameInUsers (o como quieras llamarlo)

Abra el archivo de migración que se acaba de generar y agregue esta línea en el método (entre def change y end):

rename_column :table_name, :the_name_you_want_to_change, :the_new_name

Guarde el archivo y ejecute rake db:migrate en la consola

Echa un vistazo a tu schema.db para ver si el nombre ha cambiado realmente en la base de datos!

Espero que esto ayude:)

 4
Author: Maddie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-23 16:10:36

Generar una migración de Ruby on Rails :

$:> rails g migration Fixcolumnname

Insertar código en el archivo de migración (XXXXXfixcolumnname.po):

class Fixcolumnname < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end
 3
Author: vipin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-03 22:00:14
 def change
    rename_column :table_name, :old_column_name, :new_column_name
  end
 3
Author: Apoorv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-08 18:01:21

Abre tu consola de Ruby on Rails e introduce:

ActiveRecord::Migration.rename_column :tablename, :old_column, :new_column
 2
Author: rinold simon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-03 21:58:51

Tienes dos maneras de hacer esto:

  1. En este tipo se ejecuta automáticamente el código inverso de la misma, cuando rollback.

    def change
      rename_column :table_name, :old_column_name, :new_column_name
    end
    
  2. Para este tipo, ejecuta el método up cuando rake db:migrate y ejecuta el método down cuando rake db:rollback:

    def self.up
      rename_column :table_name, :old_column_name, :new_column_name
    end
    
    def self.down
      rename_column :table_name,:new_column_name,:old_column_name
    end
    
 2
Author: Sarwan Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-05 05:10:58

Estoy en rails 5.2, y tratando de cambiar el nombre de una columna en un usuario de devise.

El bit rename_column funcionó para mí, pero el singular :table_name arrojó un error de "Tabla de usuarios no encontrada". Plural funcionó para mí.

rails g RenameAgentinUser

Luego cambie el archivo de migración a esto:

rename_column :users, :agent?, :agent

Donde :agente? es el antiguo nombre de la columna.

 1
Author: tomb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-06 13:42:53

Simplemente genere la migración usando el comando

rails g migration rename_hased_password

Después de eso, edite la migración, agregue la siguiente línea en el método de cambio

rename_column :table, :hased_password, :hashed_password

Esto debería hacer el truco.

 0
Author: Ratnam Yadav,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-05 12:02:57

Cambios en la migración de Rails 5

Eg:

Rails g model Student student_name:string age: integer

Si desea cambiar la columna student_name como name

Nota: - si no ejecuta rails db: migrar

Puede hacer los siguientes pasos

Rails d model Student student_name:string age: integer

Esto eliminará el archivo de migración generado, ahora puede corregir el nombre de su columna

Rails g model Nombre del estudiante: string edad: integer

Si ha migrado (rails db: migrate), siga las opciones para cambiar el nombre de la columna

Rails g migration RemoveStudentNameFromStudent student_name: string

Rails g migration AddNameToStudent name: string

 0
Author: prasanthrubyist,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-20 12:08:30

Update - Un primo cercano de create_table es change_table, usado para cambiar tablas existentes. Se usa de manera similar a create_table pero el objeto cedido al bloque sabe más trucos. Por ejemplo:

class ChangeBadColumnNames < ActiveRecord::Migration
  def change
    change_table :your_table_name do |t|
      t.rename :old_column_name, :new_column_name
    end
  end
end

Esta manera es más eficiente si lo hacemos con otros métodos alterados como: remove / add index/remove index / add column, por ejemplo, podemos hacer más como:

# Rename
t.rename :old_column_name, :new_column_name
# Add column
t.string :new_column
# Remove column
t.remove :removing_column
# Index column
t.index :indexing_column
#...
 -1
Author: Hieu Pham,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-21 05:32:00