Lo sviluppo di un'applicazione non significa solo implementare nuove funzioni o applicare patch. A volte è necessario invertire le modifiche e tornare alla fase precedente del progetto. Un problema frequente che può presentarsi quando si lavora su più rami è legato al mantenimento della versione appropriata di una struttura di database. I programmatori che utilizzano rails hanno a disposizione soluzioni già pronte. Queste soluzioni supportano l'implementazione e il controllo delle modifiche al database: si tratta delle migrazioni. Non descriverò come funziona e quali possibilità offre, ma vorrei concentrarmi sul problema del mantenimento della versione appropriata di una struttura di database durante il passaggio da un ramo all'altro.
Il livello di database di un'applicazione è un essere separato ed è controllato solo dalle migrazioni. Durante la creazione di nuove migrazioni, ricordate di rendere reversibile la trasformazione pianificata della struttura del database. Naturalmente, in casi estremi, si può alzare il livello di Migrazione irreversibile
nel giù metodo. Questo ci informerà anche del fatto che la migrazione non può essere annullata. La migrazione prevede diversi tipi di modifiche: creazione, modifica e rimozione di tabelle, colonne o indici. Le operazioni di eliminazione e modifica sono le più sensibili alle modifiche. Perché? Consideriamo il seguente scenario: stiamo lavorando con il ramo master, che è il nostro percorso di lavoro principale. Attualmente abbiamo una tabella:
classe CreateArticles < ActiveRecord::Migration
def modifica
creare_tabella :articoli do |t|
t.string :nome
t.text :descrizione
t.string :status, null: false
t.timestamps null: false
fine
fine
fine
Il nostro Articolo
Il modello ha tali convalide che richiedono la presenza di nome, descrizione e stato attributi.
classe Articolo < ActiveRecord::Base
convalida :nome, presenza: true
convalida :description, presenza: true
convalida :status, presenza: true
fine
Stiamo implementando cambiamenti nella nostra articoli tavolo su caratteristica e cancelliamo il ramo di sviluppo stato colonna.
classe RemoveStatusColumnFromArticles < ActiveRecord::Migration
def modifica
rimuovere_colonna :articoli, :stato, :stringa
fine
fine
Eseguiamo la migrazione:
$ [esempio/caratteristica]: bundle exec rake db:migrate
== 20150605120955 RemoveStatusColumnFromArticles: migrazione ===================
-- remove_column(:articles, :status, :string)
-> 0.0717s
== 20150605120955 RemoveStatusColumnFromArticles: migrato (0.0718s) ==========
Lo schema di un database cambia:
diff --git a/db/schema.rb b/db/schema.rb
index 2a100a9..76438c1 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,14 +11,13 @@ #
Si raccomanda vivamente di inserire questo file nel proprio sistema di controllo delle versioni.
-ActiveRecord::Schema.define(versione: 20150605120350) do
+ActiveRecord::Schema.define(versione: 20150605120955) do
crea tabella "articoli", forza: :cascade do |t|
t.string "nome"
t.text "descrizione"
- t.string "status", null: false t.datetime "createdat", null: false
t.datetime "updated_at", null: false
fine
fine
Successivamente, si effettua il commit delle modifiche al file caratteristica ramo. Per simulare questo problema, cambiamo il ramo corrente in master. La struttura di base è stata modificata dalla migrazione, che ha cancellato il file stato sulla colonna caratteristica ramo. Proviamo a usare il seguente comando:
Articolo.create!(nome: "Kaboom", descrizione: "Lorem ipsum...", stato: "attivo")
Cosa accadrà dopo l'esecuzione di quanto sopra indicato codice? L'errore: ActiveRecord::UnknownAttributeError: attributo sconosciuto 'status' per l'articolo
e questo a causa della versione incompatibile della struttura di un database. Prima di cambiare il ramo in master, dovremmo fare un rollback della migrazione che cancella il file stato dalla colonna Articolo tavolo.
Cosa possiamo fare per verificare se dobbiamo fare un rollback di alcune migrazioni prima di cambiare ramo? Con l'uso del sistema di controllo delle versioni (qui è git) possiamo verificare il nostro lavoro creando un alias utile:
~/.gitconfig
[alias]
migrations = "!f() { git diff --name-only $1..$2 db/migrate | tr -d '[A-Za-z/_.]'; }; f"
Esecuzione del git migrazioni funzione master
Il comando fornirà l'elenco delle versioni della migrazione, che si trovano in caratteristica e che non possono essere trovati su maestro.
$ [example/feature]: funzione git migrations master
20150605120955
Grazie a queste informazioni possiamo facilmente eseguire il rollback delle modifiche apportate alla struttura del database prima del passaggio a master.
$ [example/feature]: bundle exec rake db:migrate:down VERSION=20150605120955
== 20150605120955 RemoveStatusColumnFromArticles: reverting ===================
-- add_column(:articles, :status, :string)
-> 0.0009s
== 20150605120955 RemoveStatusColumnFromArticles: ripristinato (0.0045s) ==========
Un'altra cosa da fare dopo il rollback della migrazione è ripristinare lo stato di uno schema di database.
$ [esempio/caratteristica]: git status
Sul ramo feature
Modifiche non messe in scena per il commit:
(usare "git add ..." per aggiornare ciò che sarà oggetto di commit)
(usare "git checkout -- ..." per scartare le modifiche nella directory di lavoro)
modificato: db/schema.rb
nessuna modifica aggiunta al commit (usare "git add" e/o "git commit -a")
$ [esempio/caratteristica]: git checkout db/schema.rb
$ [esempio/caratteristica]: git status
Sul ramo feature
niente da impegnare, directory di lavoro pulita
Ora si può facilmente passare al metodo maestro ramo.
L'esempio fornito non è un problema complicato da risolvere, ma dovrebbe aiutarvi a capire quanto sia importante mantenere la struttura di un database durante il cambiamento del contesto di lavoro.