web-dev-qa-db-fra.com

Colonne Migration de Rails for Change

Nous avons la syntaxe script/generate migration add_fieldname_to_tablename fieldname:datatype pour ajouter de nouvelles colonnes à un modèle.

Sur la même ligne, avons-nous un script/generate pour changer le type de données d'une colonne? Ou devrais-je écrire SQL directement dans ma migration Vanilla?

Je veux changer une colonne de datetime à date.

303
papdel

Je pense que cela devrait fonctionner.

change_column :table_name, :column_name, :date
517
Alex Korban

Vous pouvez également utiliser un bloc si vous avez plusieurs colonnes à modifier dans une table.

Exemple:

change_table :table_name do |t|
  t.change :column_name, :column_type, {options}
end

Voir la documentation API sur la classe Table pour plus de détails.

96
John

Je ne sais pas si vous pouvez créer une migration à partir de la ligne de commande pour faire tout cela, mais vous pouvez créer une nouvelle migration, puis éditer la migration pour effectuer cela.

Si nom_table est le nom de votre table, nom_zone est le nom de votre champ et que vous souhaitez passer d'une date à une date, vous pouvez écrire une migration à cette fin.

Vous pouvez créer une nouvelle migration avec:

Rails g migration change_data_type_for_fieldname

Puis éditez la migration pour utiliser change_table:

class ChangeDataTypeForFieldname < ActiveRecord::Migration
  def self.up
    change_table :tablename do |t|
      t.change :fieldname, :date
    end
  end
  def self.down
    change_table :tablename do |t|
      t.change :fieldname, :datetime
    end
  end
end

Puis lancez la migration:

rake db:migrate
84
Ryan

Comme je l'ai trouvé dans les réponses précédentes, trois étapes sont nécessaires pour changer le type d'une colonne:

Étape 1:

Générez un nouveau fichier de migration en utilisant ce code:

Rails g migration sample_name_change_column_type

Étape 2: 

Accédez au dossier /db/migrate et modifiez le fichier de migration que vous avez créé. Il y a deux solutions différentes.

  1. def change
        change_column(:table_name, :column_name, :new_type)
    end
    

2.

    def up
        change_column :table_name, :column_name, :new_type
    end

    def down
        change_column :table_name, :column_name, :old_type
    end

Étape 3:

N'oubliez pas de faire cette commande:

rake db:migrate

J'ai testé cette solution pour Rails 4 et cela fonctionne bien.

28
Aboozar Rajabi

Avec des rails 5

De Rails Guides :

Si vous souhaitez qu'une migration fasse quelque chose qu'Active Record ne sait pas inverser, vous pouvez utiliser reversible :

class ChangeTablenameFieldname < ActiveRecord::Migration[5.1]
  def change
    reversible do |dir|
      change_table :tablename do |t|
        dir.up   { t.change :fieldname, :date }
        dir.down { t.change :fieldname, :datetime }
      end
    end
  end
end
6
Mr. Tao

Il suffit de générer une migration:

Rails g migration change_column_to_new_from_table_name

Mettez à jour la migration comme ceci:

class ClassName < ActiveRecord::Migration
    change_table :table_name do |t|
      t.change :column_name, :data_type
    end
end

et enfin

rake db:migrate
6
Vivek Sharma

Une autre façon de changer le type de données en utilisant la migration

étape 1: Vous devez supprimer le nom de champ du type de données défaillant à l'aide de la migration.

ex:

Rails g migration RemoveFieldNameFromTableName field_name:data_type

Ici, n'oubliez pas de spécifier le type de données pour votre champ

Étape 2: Maintenant, vous pouvez ajouter un champ avec le type de données correct

ex:

Rails g migration AddFieldNameToTableName field_name:data_type

Ça y est, maintenant votre table sera ajoutée avec le champ de type de données correct, codage Happy Ruby !!

1
prasanthrubyist

Compléter les réponses en cas d’édition valeur par défaut :

Dans votre console Rails:

Rails g migration MigrationName

Dans la migration:

  def change
    change_column :tables, :field_name, :field_type, default: value
  end

Ressemblera :

  def change
    change_column :members, :approved, :boolean, default: true
  end
0
Gregdebrick

Tout cela suppose que le type de données de la colonne ait une conversion implicite pour toutes les données existantes. J'ai rencontré plusieurs situations dans lesquelles les données existantes, disons une String peuvent être implicitement converties dans le nouveau type de données, disons Date

Dans ce cas, il est utile de savoir que vous pouvez créer des migrations avec des conversions de données. Personnellement, j'aime bien les placer dans mon fichier de modèle, puis les supprimer une fois que tous les schémas de base de données ont été migrés et sont stables.

/app/models/table.rb
  ...
  def string_to_date
    update(new_date_field: date_field.to_date)
  end

  def date_to_string
    update(old_date_field: date_field.to_s)
  end
  ...
    def up
        # Add column to store converted data
        add_column :table_name, :new_date_field, :date
        # Update the all resources
        Table.all.each(&:string_to_date)
        # Remove old column
        remove_column :table_name, :date_field
        # Rename new column
        rename_column :table_name, :new_date_field, :date_field
    end

    # Reversed steps does allow for migration rollback
    def down
        add_column :table_name, :old_date_field, :string
        Table.all.each(&:date_to_string)
        remove_column :table_name, :date_field
        rename_column :table_name, :old_date_field, :date_field
    end
0
Sebastian Scholl