Å utvikle en app betyr ikke bare å implementere nye funksjoner eller patche den. Noen ganger må man reversere endringene og gå tilbake til forrige fase av et prosjekt. Et vanlig problem som kan oppstå når man jobber med flere grener, er å opprettholde den riktige versjonen av en databasestruktur. Programmerere som bruker rails, har ferdige løsninger til rådighet. Disse løsningene støtter implementering og kontroll av databaseendringer - dette er migreringer. Jeg vil ikke beskrive hvordan det fungerer og hvilke muligheter det gir - jeg vil fokusere på problemet med å opprettholde den riktige versjonen av en databasestruktur mens du bytter filialer.
Databaselaget i en app er et eget vesen og styres kun av migreringer. Når du oppretter nye migreringer, må du huske å gjøre den planlagte transformasjonen av en databasestruktur reversibel. I ekstreme tilfeller kan vi selvfølgelig heve IrreversibelMigrasjon
i ned metode. Dette vil også informere oss om at migreringen ikke kan reverseres. Vi gjør ulike typer endringer i migreringen - vi oppretter, endrer og fjerner tabeller, kolonner eller indekser. Sletting og modifisering er de mest følsomme for endringer. Hvorfor er det slik? La oss se på følgende scenario: Vi jobber med master-grenen, som er vår viktigste arbeidssti. For øyeblikket har vi én tabell:
class CreateArticles < ActiveRecord::Migrering
def change
create_table :artikler do |t|
t.string :navn
t.text :description
t.string :status, null: false
t.timestamps null: false
end
end
end
Vår Artikkel
modellen har slike valideringer som krever tilstedeværelse av navn, beskrivelse og status attributter.
class Artikkel < ActiveRecord::Base
validerer :name, presence: true
validerer :description, presence: true
validerer :status, presence: true
end
Vi er i ferd med å implementere endringer i vår artikler bord på funksjon utviklingsgrenen, og vi sletter status spalte.
class RemoveStatusColumnFromArticles < ActiveRecord::Migrering
def endre
remove_column :artikler, :status, :string
end
end
Vi gjennomfører migreringen:
$ [eksempel/funksjon]: bundle exec rake db:migrate
== 20150605120955 RemoveStatusColumnFromArticles: migrering ===================
-- remove_column(:articles, :status, :string)
-> 0.0717s
== 20150605120955 RemoveStatusColumnFromArticles: migrert (0.0718s) ==========
Skjemaet for en database endres:
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 @@ #
Det anbefales på det sterkeste at du sjekker denne filen inn i ditt versjonskontrollsystem.
-ActiveRecord::Schema.define(version: 20150605120350) do
+ActiveRecord::Schema.define(versjon: 20150605120955) do
createtable "articles", force: :cascade do |t|
t.string "navn"
t.text "beskrivelse"
- t.string "status", null: false t.datetime "createdat", null: false
t.datetime "updated_at", null: false
slutt
end
Deretter overfører vi endringene til funksjon gren. For å simulere dette problemet bytter vi den gjeldende grenen til master. Basisstrukturen ble endret ved migrering, noe som sletter status kolonnen på funksjon forgrening. La oss prøve å bruke følgende kommando:
Article.create!(name: "Kaboom", description: "Lorem ipsum...", status: "active")
Hva vil skje etter at du har utført ovennevnte kode? Feilen: ActiveRecord::UnknownAttributeError: ukjent attributt 'status' for artikkel
vil bli utløst, og det er på grunn av den inkompatible strukturversjonen av en database. Før vi endrer grenen til master, bør vi rulle tilbake en migrering som sletter status kolonnen fra Artikkel bord.
Hva kan vi gjøre for å sjekke om vi må rulle tilbake noen migreringer før vi bytter gren? Ved hjelp av versjonskontrollsystemet (her er det git) kan vi kontrollere arbeidet vårt ved å opprette et nyttig alias:
~/.gitconfig
[alias]
migrations = "!f() { git diff --name-only $1..$2 db/migrate | tr -d '[A-Za-z/_.]'; }; f"
Utførelse av git migrations master-funksjon
kommandoen vil resultere i en liste over migreringsversjoner, som ligger på funksjon grener, og som ikke finnes på mester.
$ [example/feature]: git migrations master-funksjon
20150605120955
Takket være denne informasjonen kan vi enkelt rulle tilbake endringene som er gjort i databasestrukturen før vi bytter til master.
$ [eksempel/funksjon]: bundle exec rake db:migrate:down VERSION=20150605120955
== 20150605120955 RemoveStatusColumnFromArticles: reverting ===================
-- add_column(:articles, :status, :string)
-> 0.0009s
== 20150605120955 RemoveStatusColumnFromArticles: reverted (0.0045s) ==========
En annen ting vi bør gjøre etter at vi har rullet tilbake migreringen, er å gjenopprette statusen til et databaseskjema.
$ [eksempel/funksjon]: git-status
På grenfunksjon
Endringer ikke iscenesatt for commit:
(bruk "git add ..." for å oppdatere det som skal committes)
(bruk "git checkout -- ..." for å forkaste endringer i arbeidskatalogen)
endret: db/schema.rb
ingen endringer lagt til commit (bruk "git add" og/eller "git commit -a")
$ [eksempel/funksjon]: git checkout db/schema.rb
$ [eksempel/funksjon]: git status
På grenfunksjon
ingenting å committe, arbeidskatalog ren
Nå kan vi enkelt bytte til mester gren.
Eksemplet er ikke et komplisert problem å løse, men det bør hjelpe deg til å innse hvor viktig det er å opprettholde strukturen i en database under endringer i arbeidskonteksten.