81

Alla prima migrazione, ho dichiarato su una colonna content di essere una stringa Activerecord ha reso tale stringa (255) in base a annotate gem.Modifica di un tipo di colonna su stringhe più lunghe nei binari

Dopo spingo l'applicazione per Heroku, che utilizza Postgres, se entro nella forma in contenuto di una stringa più lunga di 255 ottengo l'errore

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

Il problema è che ho bisogno che il contenuto per contenere una stringa che è estremamente lungo forse (testo libero, potrebbe essere migliaia di caratteri)

  1. Quale variabile (la stringa non è appropriata per questo) avrebbe accettato pg?
  2. Come faccio a creare una migrazione per sostituire il tipo di quella colonna

grazie

risposta

193

si dovrebbe usare text con Rails, se si desidera una stringa senza limite di lunghezza. Una migrazione come questa:

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 

dovrebbe risolvere le cose. Potresti volere :null => false o qualche altra opzione alla fine di quello.

Quando si utilizza una colonna string senza un limite esplicito, Rails aggiungerà un numero implicito :limit => 255. Ma se usi text, otterrai qualunque tipo di stringa di lunghezza arbitraria supportata dal database. PostgreSQL ti permette di usare una colonna varchar senza una lunghezza, ma la maggior parte dei database usa un tipo separato per quello e Rails non sa di varchar senza una lunghezza. Devi usare text in Rails per ottenere un text column in PostgreSQL. Non c'è differenza in PostgreSQL tra una colonna di tipo text e una di tipo varchar (ma varchar(n)è diverso). Inoltre, se si sta implementando su PostgreSQL, non c'è alcun motivo per utilizzare :string (AKA varchar), il database tratta lo text e lo varchar(n) lo stesso internamente eccetto per i vincoli di lunghezza extra per varchar(n); si dovrebbe usare solo varchar(n) (AKA :string) se si dispone di un vincolo esterno (come un modulo governativo che dice che il campo 432 sul modulo 897/B avrà una lunghezza di 23 caratteri) sulla dimensione della colonna.

Per inciso, se si utilizza una colonna string da nessuna parte, si deve sempre specificare il :limit come promemoria per te stesso che c'è un limite e si dovrebbe avere una validazione del modello per garantire che il limite non venga superato . Se superi il limite, PostgreSQL si lamenterà e genererà un'eccezione, MySQL troncerà tranquillamente la stringa o si lamenterà (a seconda della configurazione del server), SQLite lo lascerà passare così com'è, e altri database faranno qualcos'altro (probabilmente si lamenteranno) .

Inoltre, dovresti anche sviluppare, testare e distribuire sullo stesso database (che di solito sarà PostgreSQL su Heroku), dovresti anche usare le stesse versioni del server del database. Esistono altre differenze tra i database (come il comportamento di GROUP BY) di cui ActiveRecord non ti isolerà. Potresti farlo già ma ho pensato di parlarne comunque.

+13

Grande risposta. Una nota: attualmente Rails non supporta change_column con il metodo di modifica (http://guides.rubyonrails.org/migrations.html#using-the-change-method); se la memoria serve, creerai una migrazione irreversibile se lo fai. Meglio fare il vecchio modo con i metodi su/giù. – poetmountain

+0

@BourbonJockey: è logico che 'change' non sia in grado di invertire automaticamente una modifica del tipo e la [Guida alla migrazione] (http://guides.rubyonrails.org/migrations.html#anatomy-of-a- migrazione) dice che "[il metodo di modifica] Questo metodo è preferito per la scrittura di migrazioni costruttive (aggiungendo colonne o tabelle)" e 'change_column' non è nella lista in cui punti, quindi penso che tu abbia ragione. L'ho corretto per usare 'up' /' down' (con un avvertimento su 'down'), grazie per l'heads up. –

+4

Per il futuro riferimento di altri lettori, la conversione da stringa a testo in Postgres su Heroku in questo modo NON perderà i dati. –

0

Mentre la risposta accettata è eccellente, volevo aggiungere qui una risposta che, si spera, affronti meglio la domanda di poster originale parte 2, per non esperti come me.

  1. How do I create a migration to replace the type of that column

generare migrazione impalcatura

È possibile generare una migrazione per contenere la modifica digitando la console (basta sostituire il table per il nome tavoli, e column per voi nome di colonna)

rails generate migrate change_table_column 

Ciò genererà la migrazione di scheletro all'interno dell'applicazione Rails/db/migrate/folder. Questa migrazione è un segnaposto per il tuo codice di migrazione.

Per esempio voglio creare una migrazione per cambiare il tipo di una colonna string-text, in una tabella chiamata TodoItems:

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

Esecuzione della migrazione

Una volta che hai inserito il codice per cambiare la colonna appena eseguita:

rake db:migrate 

Per applicare i tuoi migrati sopra. Se si commette un errore è sempre possibile annullare la modifica con:

rake db:rollack 

Su e Giù metodi

i riferimenti risposta accettata Up e Down metodi, invece del metodo più recente Change. Poiché le guide 3.2vecchio stile, i metodi su e giù hanno presentato alcuni vantaggi rispetto al metodo di modifica più recente. 'Su e Giù' evita ActiveRecord::IrreversibleMigration exception. Dopo il rilascio di Rails 4 è possibile utilizzare reversible per evitare questo errore:

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 

Godetevi Rails :)

Problemi correlati