Renommer la table dans les rails

154

Je veux renommer une table ... (n'importe quelle table.)

J'ai essayé cette ligne de code:

ActiveRecord::ConnectionAdapters::SchemaStatements.rename_table(old_name, new_name)

Voici la chose étrange. Je sais que je l'ai fait fonctionner la première fois, mais maintenant j'obtiens cette erreur: méthode non définie `rename_table 'pour ActiveRecord :: ConnectionAdapters :: SchemaStatements: Module

Y a-t-il quelque chose que je dois régler?

Tommy
la source

Réponses:

248

Vous feriez généralement ce genre de chose lors d'une migration:

class RenameFoo < ActiveRecord::Migration
  def self.up
    rename_table :foo, :bar
  end

  def self.down
    rename_table :bar, :foo
  end
end
came
la source
1
Merci qui a fonctionné! Je me demande toujours pourquoi la ligne précédente ne l'a pas fait. Oh bien ..
Tommy
@Tommy, la rename_tableméthode est définie dans le ActiveRecord::ConnectionAdapters::SchemaStatements. Il est destiné à être mélangé à d'autres modules. Si vous vouliez l'exécuter directement, je pense que vous pourriez le faireinclude ActiveRecord::ConnectionAdapters::SchemaStatements; rename_table :foo, :bar
cam
ou vous pouvez utiliser ActiveRecord :: Migration.rename_table (: foo,: bar) si vous le souhaitez. Mais la migration fonctionne mieux. Souhaitez-vous également modifier le nom du modèle ou conserver le nom du modèle comme l'ancien? Si c'est le cas, vous pouvez spécifier le nom de la table dans le modèle ActiveRecord en utilisant "set_table_name: bar".
Aditya Sanghi
1
Vous pouvez également utiliser le nouveau formulaire pour les migrations avec la méthode 'change' au lieu de up & down. exemple
MegaTux
def change, pas def self.up / def.self.down dans les implémentations Rails modernes. Faire ce dernier échouera silencieusement.
huertanix
294

N'oubliez pas que dans Rails> = 3.1, vous pouvez utiliser la changeméthode.

 class RenameOldTableToNewTable < ActiveRecord::Migration
   def change
     rename_table :old_table_name, :new_table_name
   end 
 end
Mikhail Grishko
la source
37
Cela permettra également de migrer tous les index de :old_table_namevers:new_table_name
Gavin Miller
7
Juste un petit commentaire: peut-être changer en: old_named_things,: new_named_things pour rappeler aux gens que les noms de table dans activerecord sont généralement pluralisés.
Carpela
24

.rename_table est une méthode d'instance, pas une méthode de classe, donc appeler Class.method ne fonctionnera pas. Vous devez créer à la place une instance de la classe, et appeler la méthode sur l'instance, comme ceci: Class.new.method.

[EDIT] Dans ce cas, ce ActiveRecord::ConnectionAdapters::SchemaStatementsn'est même pas une classe (comme indiqué par cam), ce qui signifie que vous ne pouvez même pas en créer une instance selon ce que j'ai dit ci-dessus. Et même si vous utilisiez l'exemple de la caméra class Foo; include ActiveRecord::ConnectionAdapters::SchemaStatements; def bar; rename_table; end; end;, cela ne fonctionnerait toujours pas commerename_table soulève une exception.

D'autre part, ActiveRecord::ConnectionAdapters::MysqlAdapter c'est une classe, et c'est probablement cette classe que vous devrez utiliser pour renommer votre table (ou SQLite ou PostgreSQL, selon la base de données que vous utilisez). Maintenant, comme cela se produit, ActiveRecord::ConnectionAdapters::MysqlAdapterest déjà accessible via Model.connection, vous devriez donc être complètement capable de faireModel.connection.rename_table , en utilisant n'importe quel modèle de votre application. [/ÉDITER]

Cependant, si vous souhaitez renommer définitivement une table, je vous suggère d'utiliser une migration pour le faire. C'est facile et le moyen préféré de manipuler la structure de votre base de données avec Rails. Voici comment procéder:

# Commandline
rails generate migration rename_my_table

# In db/migrate/[timestamp]_rename_my_table.rb:
class RenameMyTable < ActiveRecord::Migration
  def self.up
    rename_table :my_table, :my_new_table
  end

  def self.down
    rename_table :my_new_table, :my_table
  end
end

Ensuite, vous pouvez exécuter votre migration avec rake db:migrate(qui appelle la self.upméthode) et utiliser rake db:rollback(qui appelle self.down) pour annuler la migration.

Vonconrad
la source
Je suis d'accord qu'il rename_tables'agit d'une méthode d'instance, mais elle n'est pas définie dans une classe, donc votre suggestion d'appeler Class.new.methodne fonctionnera pas (par exemple: ActiveRecord::ConnectionAdapters::SchemaStatements.newdonne l'erreur oMethodError: undefined method new 'for ActiveRecord :: ConnectionAdapters :: SchemaStatements: Module`
cam
1
Il convient également de souligner que si vous avez un modèle associé à la table, vous renommez , exécutez rake db:migrateou rake db:rollbackne renommez pas le fichier model.rb. Vous devrez modifier manuellement le fichier model.rb.
9monkeys
1
Dans les versions plus récentes de Rails (par exemple 5.x), vous pouvez utiliser une méthode de changement au lieu de self.up et self.down , car Rails peut également effectuer une restauration de cette manière. Il suffit donc de ce code est suffisant: def change rename_table :my_table, :my_new_table end. . . . . Soit dit en passant: A l' intérieur de changevous une utilisation de ces commandes: add_column, add_index, add_timestamps, create_table, remove_timestamps, rename_column, rename_index,rename_table
Beauté
2
ActiveRecord::Migration.rename_table(:old_table_name, :new_table_name)
imsinu9
la source