web-dev-qa-db-fra.com

Changer un type de colonne en chaînes plus longues dans rails

Lors de la première migration, j'ai déclaré sur une colonne content qu'il s'agissait d'une chaîne. Activerecord l'a transformée en chaîne (255) en fonction de l'annotation de gem.

Après avoir poussé l'application vers heroku, qui utilise postgres, si j'entre dans le formulaire dans le contenu une chaîne supérieure à 255, le message d'erreur s'affiche.

PGError: ERROR: value too long for type character varying(255)

Le problème est que j'ai besoin que ce contenu contienne une chaîne extrêmement longue peut-être (texte libre, peut-être des milliers de caractères)

  1. Quelle variable (chaîne n'est pas appropriée pour cela) pg accepterait-il?
  2. Comment créer une migration pour remplacer le type de cette colonne

merci

88
Nick Ginanto

Vous devez utiliser text avec Rails si vous voulez une chaîne sans limite de longueur. Une migration comme celle-ci:

def up
  change_column :your_table, :your_column, :text
end
def down
  # This might cause trouble if you have strings longer
  # than 255 characters.
  change_column :your_table, :your_column, :string
end

devrait régler les choses. Vous voudrez peut-être aussi :null => false Ou d'autres options à la fin de celle-ci.

Lorsque vous utilisez une colonne string sans limite explicite, Rails ajoutera un :limit => 255 Implicite. Mais si vous utilisez text, vous ' Vous obtiendrez le type de chaîne de longueur arbitraire pris en charge par la base de données. PostgreSQL vous permet d’utiliser une colonne varchar sans longueur, mais la plupart des bases de données utilisent un type distinct pour cela et Rails ne connaître varchar sans une longueur. Vous devez utiliser text in Rails pour obtenir une colonne text! dans PostgreSQL. Il n'y a pas de différence dans PostgreSQL entre une colonne de type text et une de type varchar (mais varchar(n) est différent. De plus, si vous déployez sur PostgreSQL, il n’ya aucune raison d’utiliser :string (AKA varchar), la base de données traite text et varchar(n) identique en interne, à l'exception des contraintes de longueur supplémentaires pour varchar(n); vous ne devez utiliser varchar(n) (AKA :string) que si vous avez contrainte externe (comme un formulaire gouvernemental indiquant que le champ 432 de formulaire 897/B comportera 23 caractères) sur la taille de la colonne.

En passant, si vous utilisez une colonne string n'importe où, vous devez toujours spécifier le :limit Pour vous rappeler qu'il existe une limite et que vous devez disposer d'une validation dans le modèle pour garantir que la limite n'est pas dépassée. Si vous dépassez la limite, PostgreSQL se plaindra et lèvera une exception, MySQL tronquera discrètement la chaîne ou se plaindra (selon la configuration du serveur), SQLite le laissera passer tel quel, et d'autres bases de données feront autre chose (probablement se plaindront). .

En outre, vous devriez également développer, tester et déployer sur la même base de données (qui sera généralement PostgreSQL chez Heroku), vous devriez même utiliser les mêmes versions du serveur de base de données. Il existe d'autres différences entre les bases de données (telles que le comportement de GROUP BY) sur lesquelles ActiveRecord ne vous isolera pas. Vous le faites peut-être déjà, mais je pensais le mentionner de toute façon.

208
mu is too short

Bien que la réponse acceptée soit excellente, je voulais ajouter ici une réponse qui, espérons-le, traite mieux avec la question 2 des affiches originales, pour des non experts comme moi.

  1. Comment créer une migration pour remplacer le type de cette colonne

générant une migration d'échafaudage

Vous pouvez générer une migration pour conserver votre modification en tapant dans votre console (remplacez simplement le table pour le nom de votre table et column pour votre nom de colonne)

Rails generate migration change_table_column

Cela générera une migration squelette à l'intérieur de votre dossier Rails application/db/migrate /. Cette migration est un espace réservé pour votre code de migration.

Par exemple, je souhaite créer une migration pour changer le type d'une colonne de string à text, dans une table appelée TodoItems:

class ChangeTodoItemsDescription < ActiveRecord::Migration
  def change
     # enter code here
     change_column :todo_items, :description, :text
  end
end

Exécution de votre migration

Une fois que vous avez entré le code pour changer la colonne, lancez:

rake db:migrate

Pour appliquer votre migration. Si vous faites une erreur, vous pouvez toujours annuler la modification avec:

rake db:rollack

Méthodes de haut en bas

La réponse acceptée fait référence aux méthodes Up et Down, au lieu de la méthode plus récente Change. Depuis Rails .2 ancien style Les méthodes Up et Down présentent quelques avantages par rapport à la nouvelle méthode Change. 'Up and Down' éviter ActiveRecord::IrreversibleMigration exception. Depuis la publication de Rails 4 , vous pouvez utiliser reversible pour éviter cette erreur:

class ChangeProductsPrice < ActiveRecord::Migration
  def change
    reversible do |dir|
      change_table :products do |t|
        dir.up   { t.change :price, :string }
        dir.down { t.change :price, :integer }
      end
    end
  end
end

Profitez de Rails :)

5
Tony Cronin