Migration de Rails – change_column avec conversion de type

Je suis déjà un peu sur Google et il semble qu’il n’y ait pas de réponse satisfaisante à mon problème.

J’ai une table avec une colonne de type ssortingng. Je voudrais courir après la migration:

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

Quand je cours cela, j’obtiens l’erreur suivante

 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 

Je sais que je peux effectuer cette migration à l’aide de SQL pur, mais que ce serait mieux si je pouvais le faire avec Rails. Je suis passé par le code Rails et semble ne pas avoir une telle possibilité, mais peut-être que quelqu’un connaît un moyen?

Je ne suis pas intéressé par: – le SQL pur – la suppression de la colonne – la création d’une autre colonne, la conversion des données, la suppression de l’original et le renommage

Si vos chaînes dans la colonne smoking sont déjà des valeurs booléennes valides, l’instruction suivante va changer le type de colonne sans perdre de données:

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

De même, vous pouvez utiliser cette instruction pour transtyper les colonnes en entier:

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

J’utilise Postgres. Vous ne savez pas si cette solution fonctionne pour d’autres bases de données.

Toutes les bases de données ne permettent pas de modifier le type de colonne, l’approche généralement adoptée consiste à append une nouvelle colonne du type souhaité, à transférer les données, à supprimer l’ancienne colonne et à renommer la nouvelle.

 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 

Alors bon pour booléen en postgres:

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

et vous pouvez en append d’autres WHENTHEN condition dans votre expression

Pour les autres serveurs de firebase database, l’expression sera construite en fonction de la syntaxe de votre serveur de firebase database, mais le principe est le même. Seul l’algorithme de conversion manuelle, entièrement sans SQL, ne suffit malheureusement pas.

Way with syntax change_column :table, :filed, 'boolean USING CAST(field AS boolean)' ne convient que si le contenu du champ quelque chose comme: true / false / null

Comme j’utilise Postgres, je suis parti avec la solution SQL pour le moment. Requête utilisée:

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

Cela ne fonctionne que si l’on a un champ rempli de chaînes true / false (comme par exemple, l’assistant de collecte de boutons radio par défaut avec un type booléen forcé générerait)