Exécuter un seul fichier de migration


267

Existe-t-il un moyen simple d'exécuter une seule migration? Je ne veux pas migrer vers une certaine version, je veux juste en exécuter une spécifique.


Est-ce quelque chose que vous avez exécuté une fois en tant que migration, car il s'est avéré nécessaire, puis s'est avéré être une requête utile qui pourrait avoir besoin d'être exécutée plusieurs fois? vous devriez peut-être refactoriser le contenu de la migration dans un modèle ou un autre objet, puis avoir la référence de migration vers ce nouvel emplacement. Ensuite, vous pouvez simplement exécuter le nouvel objet à votre lésion en appelant ruby ​​sur la ligne de commande.
Nathan Feger

Réponses:


240

Vous pouvez simplement exécuter le code directement à partir du fichier ruby:

rails console
>> require "db/migrate/20090408054532_add_foos.rb"
>> AddFoos.up

Remarque: les versions plus récentes des rails peuvent nécessiter AddFoos.new.upplutôt que AddFoos.up.

Une manière alternative (sans IRB) qui repose sur le fait que require retourne un tableau de noms de classe:

script/runner 'require("db/migrate/20090408054532_add_foos.rb").first.constantize.up'

Notez que si vous faites cela, cela ne mettra probablement pas à jour le schema_migrationstableau, mais il semble que c'est ce que vous voulez de toute façon.


59
Parfois, vous avez besoin d'un './' devant le chemin requis, et il ne met définitivement pas à jour les schema_migrations.
Beardo

14
J'ai dû créer une instance de l'objet de migration avant de pouvoir appeler. par exempleAddFoos.new.up
Bentleyo

15
Donc, pour résumer Rails 3.2: require "./db/migrate/db/migrate/20090408054532_add_foos.rb"alorsAddFoos.new.up
trisweb

50
Si votre migration utilise à la changeplace de upet down, vous devrez exécuterAddFoos.new.migrate(:up)
Don Werve

6
Dans les rails 4, vous pouvez appelerAddFoos.new.change
lfender6445

429

En supposant une version assez récente de Rails, vous pouvez toujours exécuter:

rake db:migrate:up VERSION=20090408054532

Où version correspond à l'horodatage du nom de fichier de la migration.

Edit: à un moment donné au cours des 8 dernières années (je ne sais pas quelle version) Rails a ajouté des contrôles qui empêchent cela de fonctionner s'il a déjà été exécuté. Ceci est indiqué par une entrée dans le schema_migrationstableau. Pour le réexécuter, exécutez simplement à la rake db:migrate:redo VERSION=20090408054532place.


124
En fait, la commande est rake db: migrate: redo VERSION = my_version
Chirag Patel

2
@Chirag Patel: C'est exactement ce que je cherchais! Merci!
Abel

23
redo exécute la méthode down de la migration donnée et la méthode up après cela. up ne fonctionne que par la méthode up, et je pense que c'est exactement ce que la personne qui demande.
Sven Koschnicke

7
'up' semble ne pas s'exécuter si la version du schéma de base de données est postérieure à la migration en question, ce qui peut se produire lors de la fusion des modifications d'une autre personne, par exemple.
Matt Connolly

3
Merci, je l'ai utilisé pourrake db:migrate:down VERSION=XXX
Nitrodist

107

Si vous souhaitez exécuter une migration spécifique , faites

$ rake db:migrate:up VERSION=20080906120000

Si vous souhaitez exécuter des migrations plusieurs fois , faites

# use the STEP parameter if you need to go more than one version back
$ rake db:migrate:redo STEP=3

Si vous souhaitez exécuter une seule migration plusieurs fois, faites

# this is super useful
$ rake db:migrate:redo VERSION=20080906120000

(vous pouvez trouver le numéro de version dans le nom de fichier de votre migration)


Modifier: Vous pouvez également simplement renommer votre fichier de migration, par exemple:

20151013131830_my_migration.rb -> 20151013131831_my_migration.rb

Ensuite, migrez normalement, cela traitera la migration comme une nouvelle (utile si vous souhaitez migrer sur un environnement distant (tel que le transfert) sur lequel vous avez moins de contrôle.

Edit 2 : Vous pouvez également simplement supprimer l'entrée de migration dans la base de données. Par exemple:

rails_c> q = "delete from schema_migrations where version = '20151013131830'"
rails_c> ActiveRecord::Base.connection.execute(q)

rake db:migrateva ensuite relancer la upméthode des migrations nucléaires.


"Up" et "redo" ne fonctionnaient pas pour moi, mais la suppression de la ligne dans schema_migrations était parfaite.
Cesoid

27

Si vous avez implémenté une changeméthode comme celle-ci:

class AddPartNumberToProducts < ActiveRecord::Migration
  def change
    add_column :products, :part_number, :string
  end
end

Vous pouvez créer une instance de la migration et exécuter migrate(:up)ou migrate(:down)sur une instance, comme ceci:

$ rails console
>> require "db/migrate/20090408054532_add_part_number_to_products.rb"
>> AddPartNumberToProducts.new.migrate(:down)

1
Cela s'applique également même si vous utilisez upet down.
gak

17

Voici les étapes pour relancer ce fichier de migration "20150927161307_create_users.rb"

  1. Exécutez le mode console. (rails c)
  2. Copiez et collez la classe qui se trouve dans ce fichier sur la console.

    class CreateUsers < ActiveRecord::Migration
      def change
        create_table :users do |t|
          t.string :name
          t.string :email
          t.timestamps null: false   end
        end
      end
    end
  3. Créez une instance de la classe CreateUsers:c1 = CreateUsers.new

  4. Exécutez la méthode changede cette instance:c1.change

il suffit d'exiger le fichier avec la classe, par exemple dans la console: require "./db/migrate/20150927161307_create_users.rb"au lieu de copier et coller. Vous pouvez ensuite exécuter la classe de la même manière en instanciant et en appelant la méthode définie dans la classe CreateUsers.new.change.
VinnyQ77

13

En tant que rails 5vous pouvez également utiliser railsau lieu derake

Rails 3 à 4

# < rails-5.0
rake db:migrate:up VERSION=20160920130051

Rails 5

# >= rails-5.0
rake db:migrate:up VERSION=20160920130051

# or

rails db:migrate:up VERSION=20160920130051

1
il devine aussi ce dont vous avez besoin avecrails db:migrate VERSION=20160920130051
frenesim

12

Si vous rencontrez des problèmes avec les chemins que vous pouvez utiliser

require Rails.root + 'db/migrate/20090408054532_add_foos.rb'

6

Méthode 1:

rake db:migrate:up VERSION=20080906120000

Méthode 2:

Dans la console Rails 1. Copiez collez la classe de migration dans la console (par exemple, add_name_to_user.rb) 2. Ensuite, dans la console, saisissez ce qui suit

Sharding.run_on_all_shards{AddNameToUser.up}

C'est fait!!


5

Veuillez noter qu'au lieu de script/runner, vous devrez peut-être utiliser rails runnersur de nouveaux environnements de rails.


3

Si vous souhaitez l'exécuter à partir de la console, voici ce que vous recherchez:

$ rails console
irb(main)> require "#{Rails.root.to_s}/db/migrate/XXXXX_my_migration.rb"
irb(main)> AddFoo.migrate(:up)

J'ai essayé les autres réponses, mais nécessitant sans Rails.rootn'a pas fonctionné pour moi.

De plus, .migrate(:up)part force la migration à être réexécutée, qu'elle ait déjà été exécutée ou non. Cela est utile lorsque vous avez déjà exécuté une migration, que vous l'avez un peu annulée en jouant avec la base de données et que vous souhaitez une solution rapide pour la réactiver.


1

Il semble qu'au moins dans la dernière version de Rails (5.2 au moment de la rédaction), il existe une autre façon de filtrer les migrations en cours d'exécution. On peut passer un filtre dans une SCOPEvariable d'environnement qui serait ensuite utilisé pour sélectionner les fichiers de migration.

En supposant que vous avez deux fichiers de migration 1_add_foos.rbet en 2_add_foos.run_this_one.rbcours d'exécution

SCOPE=run_this_one rails db:migrate:up

sélectionnera et s'exécutera uniquement 2_add_foos.run_this_one.rb. Gardez à l'esprit que tous les fichiers de migration correspondant à la portée seront exécutés.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.