Vývoj aplikace neznamená pouze implementaci nových funkcí nebo její opravu. Někdy je třeba změny zvrátit a vrátit se k předchozí fázi projektu. Častý problém, který může nastat při práci na více větvích, je spojen s udržováním příslušné verze struktury databáze. Programátoři, kteří používají rails, mají k dispozici hotová řešení. Tato řešení podporují provádění a kontrolu změn databáze - jedná se o migrace. Nebudu popisovat, jak to funguje a jaké možnosti to přináší - chtěl bych se zaměřit na problém udržování příslušné verze struktury databáze při přepínání větví.
Databázová vrstva aplikace je samostatná bytost a je řízena pouze migracemi. Při vytváření nových migrací nezapomeňte na to, aby plánovaná transformace struktury databáze byla vratná. Samozřejmě, že v extrémních případech můžeme zvýšit. IrreversibleMigration v dolů metoda. To bude také informovat nás o tom, že migraci nelze zvrátit. Při migraci provádíme různé typy změn - vytváříme, upravujeme a odstraňujeme tabulky, sloupce nebo indexy. Operace odstraňování a modifikace jsou na změny nejcitlivější. Proč? Uvažujme následující scénář: Pracujeme s hlavní větví, která je naší hlavní pracovní cestou. V současné době máme jednu tabulku:
třída CreateArticles < ActiveRecord::Migration
def change
create_table :articles do |t|
t.string :name
t.text :description
t.string :status, null: false
t.timestamps null: false
end
end
end
Naše Článek model má takové validace, které vyžadují přítomnost název, popis a stav atributy.
třída Article < ActiveRecord::Base
validates :name, presence: true
validates :description, presence: true
validates :status, presence: true
end
Provádíme změny v naší články tabulka na funkce vývojové větve a odstraníme stav sloupec.
třída RemoveStatusColumnFromArticles < ActiveRecord::Migration
def change
remove_column :articles, :status, :string
end
end
Provedeme migraci:
$ [example/feature]: bundle exec rake db:migrate
== 20150605120955 RemoveStatusColumnFromArticles: migrace ===================
-- remove_column(:articles, :status, :string)
-> 0.0717s
== 20150605120955 RemoveStatusColumnFromArticles: migrováno (0.0718s) ==========
Schéma databáze se změní:
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 @@ #
Důrazně doporučujeme, abyste tento soubor zkontrolovali ve svém systému pro správu verzí.
-ActiveRecord::Schema.define(version: 20150605120350) do
+ActiveRecord::Schema.define(version: 20150605120955) do
createtable "articles", force: :cascade do |t|
t.string "name"
t.text "description"
- t.string "status", null: false t.datetime "createdat", null: false
t.datetime "updated_at", null: false
end
end
Poté odevzdáme změny do funkce pobočka. Pro simulaci tohoto problému přepneme aktuální větev na master. Základní struktura byla změněna migrací, která odstraní tzv. stav sloupec na funkce pobočka. Zkusme použít následující příkaz:
Article.create!(name: "Kaboom", description: "Lorem ipsum...", status: "active")
Co se stane po provedení výše uvedených kód? Chyba: ActiveRecord::UnknownAttributeError: neznámý atribut 'status' pro článek a to z důvodu nekompatibilní verze struktury databáze. Před změnou větve na master bychom měli vrátit zpět migraci, která odstraní stav sloupce z Článek tabulka.
Co můžeme udělat, abychom zjistili, zda musíme některé migrace vrátit před přepnutím větví? Pomocí systému pro správu verzí (zde je to git) můžeme zkontrolovat naši práci vytvořením užitečného aliasu:
~/.gitconfig
[alias]
migrations = "!f() { git diff --name-only $1..$2 db/migrate | tr -d '[A-Za-z/_.]'; }; f"
Provedení funkce git migrations master příkazem se zobrazí seznam migračních verzí, které se nacházejí na adrese funkce a které nelze nalézt na master.
$ [example/feature]: git migrations master feature
20150605120955
Díky těmto informacím můžeme snadno vrátit zpět změny provedené ve struktuře databáze před přepnutím na master.
$ [example/feature]: bundle exec rake db:migrate:down VERSION=20150605120955
== 20150605120955 RemoveStatusColumnFromArticles: vrácení zpět ===================
-- add_column(:articles, :status, :string)
-> 0.0009s
== 20150605120955 RemoveStatusColumnFromArticles: vráceno (0.0045s) ==========
Další věcí, kterou bychom měli po vrácení migrace provést, je obnovení stavu databázového schématu.
$ [example/feature]: git status
Na větvi funkce
Změny nejsou připraveny k odevzdání:
(pro aktualizaci toho, co bude odevzdáno, použijte příkaz "git add ...")
(pro vyřazení změn v pracovním adresáři použijte "git checkout -- ...")
upraveno: db/schema.rb
do revize nebyly přidány žádné změny (použijte "git add" a/nebo "git commit -a")
$ [example/feature]: git checkout db/schema.rb
$ [example/feature]: git status
Na funkci větve
nic k odevzdání, pracovní adresář čistý
Nyní můžeme snadno přepnout na master pobočka.
Uvedený příklad nepředstavuje složitý problém k řešení, ale měl by vám pomoci uvědomit si, jak důležité je zachovat strukturu databáze při změně pracovního kontextu.