63 votes

Dans une migration Rails (MySQL), peut-on spécifier la position d'une nouvelle colonne ?

Si j'ajoute une colonne via MySQL, je peux spécifier l'emplacement de cette colonne dans la table à l'aide du modificateur AFTER. Mais si j'effectue l'ajout de colonne via une migration Rails, la colonne sera créée à la fin de la table.

Existe-t-il une fonctionnalité pour les migrations rails permettant de spécifier la position d'une colonne ajoutée ?

69voto

Gabe Martin-Dempesy Points 2414

Cela est désormais possible dans Rails 2.3.6+ en passant le paramètre :after

https://rails.lighthouseapp.com/projects/8994/tickets/3286-patch-add-support-for-mysql-column-positioning-to-migrations

Pour tous ceux qui ne voient pas l'avantage de cette fonctionnalité : ne regardez-vous jamais votre base de données en dehors de l'ORM ? Si j'utilise une interface utilisateur, j'aime avoir des éléments comme les clés étrangères, les colonnes d'état, les drapeaux, etc. regroupés. Cela n'a pas d'impact sur l'application, mais accélère définitivement ma capacité à examiner les données.

2 votes

Merci de donner une raison valable de se soucier de l'ordre des colonnes. Je ne l'avais pas vraiment compris avant de lire votre réponse. Si je regarde la base de données en dehors de l'ORM, cela signifie généralement la console de ligne de commande SQL ou une interface utilisateur où je peux mélanger les colonnes comme je le souhaite. Je n'ai pas pensé à ces nouvelles interfaces Web :-)

0 votes

Savez-vous si SQLite prend en charge l'option :after ? Je n'arrive pas à la faire fonctionner ni dans change_column ni dans add_column.

11 votes

D'ailleurs, par exemple, :after => :id vous pouvez aussi dire :first => true pour l'insérer comme première colonne.

32voto

Tamik Soziev Points 2094

Bien sûr que vous pouvez.

  • Réponse courte :

    add_column :users, :gender, :string, :after => :column_name
  • Longue réponse :

Voici un exemple, disons que vous souhaitez ajouter une colonne appelée " genre "après la colonne " nom d'utilisateur " à " utilisateurs Table ".

  1. Type rails g migration AddGenderToUser gender:string
  2. Ajouter " after => :username " dans la migration qui a été créée pour qu'elle ressemble à ceci :

    class AddSlugToDictionary < ActiveRecord::Migration
      def change
        add_column :users, :gender, :string, :after => :username
      end
    end

2 votes

Pourriez-vous ajouter un lien vers la documentation officielle ?

8voto

Ben Marini Points 71

J'ai créé un patch qui ajoute cette fonctionnalité supplémentaire à l'adaptateur Mysql d'ActiveRecord. Il fonctionne pour master et 2-3-stable.

https://rails.lighthouseapp.com/projects/8994/tickets/3286-patch-add-support-for-mysql-column-positioning-to-migrations

C'est peut-être spécifique à mysql, mais cela ne rend pas vos migrations moins portables (les autres adaptateurs ignoreront simplement les options de positionnement supplémentaires).

5voto

Bill Karwin Points 204877

Il ne semble pas y avoir d'option de position pour la add_column dans les migrations. Mais les migrations supportent l'exécution de SQL littéral. Je ne suis pas un développeur Rails, mais quelque chose comme ce qui suit :

class AddColumnAfterOtherColumn < ActiveRecord::Migration
  def self.up
    execute "ALTER TABLE table_name ADD COLUMN column_name INTEGER 
      AFTER other_column"
  end

  def self.down
    remove_column :table_name, :column_name
  end
end

0 votes

Oui, c'est ce que je fais pour mon application qui utilise une ancienne version de rails.

0 votes

Pas étonnant, puisque j'ai répondu à cette question en 2008 - avant Rails 1.0 ! N'hésitez pas à poster votre propre réponse qui fonctionne avec Rails 5.2.

0 votes

J'ai fait un essai avec miner tweet qui n'a pas été concluant.

1voto

Mike Woodhouse Points 27748

Il n'y a aucun moyen dans Rails de spécifier la position d'une colonne. En fait, je pense que ce n'est qu'une coïncidence (et qu'il ne faut donc pas s'y fier) que les colonnes soient créées dans l'ordre où elles sont nommées dans une migration.

L'ordre des colonnes dans une table est presque pertinent et devrait l'être : la "raison" couramment invoquée est de pouvoir voir un sous-ensemble particulier lors de l'exécution d'un "SELECT *", mais ce n'est vraiment pas une bonne raison.

Toute autre raison est probablement une odeur de design, mais j'aimerais bien connaître une raison valable pour laquelle je me trompe !

Sur certaines plates-formes, il y a un (minuscule) gain d'espace et de performance à obtenir en mettant les colonnes avec la plus grande probabilité d'être NULL à la fin (parce que le DMBS n'utilisera pas d'espace disque pour les valeurs NULL "traînantes", mais je pense qu'il faut être sur du matériel des années 1980 pour le remarquer.

0 votes

Ce n'est pas une coïncidence, c'est le comportement standard de SQL qui veut que ALTER TABLE ADD COLUMN ajoute la colonne comme dernière position ordinale dans la table. La syntaxe "AFTER" de MySQL est une extension du SQL standard.

0 votes

Norme ANSI ? Ou de facto ? Je ne suis pas en train de chipoter, je suis simplement curieux.

0 votes

Je m'appuie sur le livre "SQL-99 Complete, Really" qui décrit le comportement standard ANSI selon lequel les colonnes supplémentaires sont ajoutées en tant que colonne la plus à droite dans une table.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X