run remove rails migrations create column change_column ruby-on-rails ruby-on-rails-3

ruby on rails - remove - Migraciones de carriles-change_column con conversión de tipo



rollback migration rails (4)

Ya google''d surgió un poco y parece que no hay una respuesta satisfactoria para mi problema.

Tengo una tabla con columna de tipo cadena. Me gustaría ejecutar la siguiente migración:

class ChangeColumnToBoolean < ActiveRecord::Migration def up change_column :users, :smoking, :boolean end end

Cuando ejecuto esto recibo un error de seguimiento

PG::Error: ERROR: column "smoking" cannot be cast automatically to type boolean HINT: Specify a USING expression to perform the conversion. : ALTER TABLE "users" ALTER COLUMN "smoking" TYPE boolean

Sé que puedo realizar esta migración usando SQL puro, pero aún así sería mejor si pudiera hacerlo con Rails. Revisé el código de Rails y parece que no hay tal posibilidad, pero ¿alguien sabe cómo?

No estoy interesado en: - SQL puro - dejando caer la columna - creando otra columna, convirtiendo datos, soltando el original y luego cambiando el nombre


Así que correcto para booleano en postgres:

change_column :table_name, :field,''boolean USING (CASE field WHEN /'your any string as true/' THEN /'t/'::boolean ELSE /'f/'::boolean END)''

y puedes agregar algo más de WHEN - THEN en tu expresión

Para otros servidores de bases de datos, la expresión se construirá en base a la sintaxis para su servidor de base de datos, pero el principio es el mismo. Solo el algoritmo de conversión manual, completamente sin SQL, no es suficiente por desgracia.

Manera con la sintaxis change_column :table, :filed, ''boolean USING CAST(field AS boolean)'' solo es adecuado si el contenido del campo es algo así como: true / false / null


No todas las bases de datos permiten cambiar el tipo de columna, el enfoque generalmente adoptado es agregar una nueva columna del tipo deseado, traer todos los datos, eliminar la columna anterior y renombrar la nueva.

add_column :users, :smoking_tmp, :boolean User.reset_column_information # make the new column available to model methods User.all.each do |user| user.smoking_tmp = user.smoking == 1 ? true : false # If smoking was an int, for example user.save end # OR as an update all call, set a default of false on the new column then update all to true if appropriate. User.where(:smoking => 1).update_all(:smoking_tmp = true) remove_column :users, :smoking rename_column :users, :smoking_tmp, :smoking


Si sus cadenas en smoking columna de smoking ya son valores booleanos válidos, la siguiente declaración cambiará el tipo de columna sin perder datos:

change_column :users, :smoking, ''boolean USING CAST(smoking AS boolean)''

Del mismo modo, puede usar esta instrucción para convertir columnas en números enteros:

change_column :table_name, :column_name, ''integer USING CAST(column_name AS integer)''

Estoy usando Postgres. No estoy seguro de si esta solución funciona para otras bases de datos.


Ya que estoy usando Postgres, fui con la solución SQL por ahora. Consulta utilizada:

execute ''ALTER TABLE "users" ALTER COLUMN "smoking" TYPE boolean USING CASE WHEN "flatshare"=/'true/' THEN /'t/'::boolean ELSE /'f/'::boolean END''

Funciona solo si uno tiene un campo lleno de cadenas verdaderas / falsas (como por ejemplo, el asistente de recolección de botones de radio predeterminado con el tipo de booleano forzado generaría)