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.

nan
la source
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.

Orion Edwards
la source
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.

gtd
la source
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.

Benjamin Crouzier
la source
"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)
chibicode
la source
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
rolph dzounga
la source
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
Deepak Mahakale
la source
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'
Dejan Cancarevic
la source
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!!

ramya
la source
5

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

viniciusnz
la source
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.

Tasos Anesiadis
la source
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.

Szymek
la source