ThuisBalletje
TrainingenBalletje
ConsultancyBalletje
Blog Balletje
Rails en Migrations
10-07-2007

Wat zijn migrations?

Migrations zijn beschrijvingen van je database schema in Ruby. Ze hebben verder de intentie om database onafhankelijk te zijn waar mogelijk. Dus een migratie moet zowel onder PostgreSQL, MySQL, SQLite etc. werken.

Met andere woorden: een aanpassing in je database.yml als het gaat om de adapter moet geen problemen opleveren. En dat is heel cool.


Maar dat is het natuurlijk niet alleen. Het gaat ook om het gemak waarmee je je database schema kan aanmaken en bewerken met Ruby. En dat gaan we aan de hand van een kleine demo aantonen. Dus gooi even een padje dark roast in die senseo en 'buckle up'.


We gaan even uit van de situatie bedrijven en werknemers. We moeten dat gaan beschrijven voor ons nieuwe project. Oh, en doe jezelf een plezier en ga aub naar mijn artikel over SQLite3 in Rails en Tiger want dat is in combinatie met migrations hetzelfde als appeltaart met slagroom!


UPDATE → rails 2.0.2

SQLIte3 is standaard de nieuwe database adapter voor rails 2.0.2

Heb je geen installatie van SQLite3 dan het volgende gebruiken:

> rails bedrijfsleven -d mysql

Maar hier gebruiken we SQLite3.

> cd rails_junk_map

> rails bedrijfsleven

> ...

> cd bedrijfsleven

Standaard rails directory

We gaan nu het eerste model aanmaken.

> script/generate model bedrijf

En nu is het van belang om te weten dat dit ook een migration oplevert in de db directory.


migr_02


Wil je een model aanmaken zonder een migration file, dan moet je dat expliciet opgeven

> script/generate model bedrijf --skip-migration

En het is uiteraard van belang dat je de migratie aanpast voordat je het commando geeft om te migreren, want anders zal er niet veel gebeuren. Hoe ziet de kale migratie er uit?


yaml


UPDATE → rails 2.0.x

Migrations in rails 2 hebben een nieuwe syntax gekregen die we 'Sexy Migrations' noemen. Dit vanwege het feit dat het nog simpeler is geworden. De syntax is ook omgedraaid. Vroeger begonnen we met het benoemen van de naam van de column, nu met wat voor soort type het is. Verder wordt er automatisch t.timestamps aangemaakt wat de columns 'created_at' en 'updated_at' van het type datetime aanmaakt. Dus dat is een stuk sneller dan zelf elke keer die columns definieren.


Los van de foute inflectie hierboven, klik deze link als je dat wilt veranderen in bedrijven, is het duidelijk dat we nog een paar columns voor ons voorbeeld moeten aanmaken voordat we migreren. Dus we gaan een column naam en plaats toevoegen op de volgende manier:


yaml


Hier zien we dat we op een simpele manier twee colums hebben aangemaakt. Wat we hier ook zien is dat we twee columns aanmaken op één regel met t.string, wat uiteraard logischer is.

We zijn nu klaar voor een migratie.


LET OP: als je geen SQLite3 hebt dan uiteraard in MySQL eerst een database aanmaken. Ook je database.yaml file checken. Anders errors. En het password hieronder is van MySQL en niet van je Mac.

> mysqladmin -u root -p create bedrijfsleven;

Enter password:

Maar nu dan echt een migratie.

> rake db:migrate

== CreateBedrijfs: migrating ==

-- create_table(:bedrijfs)

-> 0.0022s

== CreateBedrijfs: migrated (0.0023s) ==

Simpel zat! Maar we gaan het even testen.

> ruby script/console

Loading development environment.

>> Bedrijf.column_names

=> [ "id", "naam", "plaats", "created_at", "updated_at" ]

En inderdaad het werkt.

En wat hebben we hier nu aan?

Bijvoorbeeld het volgende. We hebben allemaal wel een Maccie of een PC over. Echt zo'n bak om op te klooien. Voor migrations was het altijd f*ck, als ik een rails map ssh'de naar die Mac om er achter te komen dat ik weer een GUI op kon starten om me database te vullen. Nu is het rake db:migrate en gaan!

En ik wil nogmaals benadrukken dat je met SQLite3 helemaal geen gezeur hebt want dat is filebased en staat gewoon in je db directory. Gooi het op een USB stick en je hebt een portable rails app!

En toen konden we wel een extra column in onze database gebruiken.

Bijvoorbeeld een adres column. Hoe doe we dat?


UPDATE → rails 2.0.x

Een ander onderdeel van 'sexy migrations' is het toevoegen van een nieuwe migratie. Onze nieuwe adres column bijvoorbeeld:

> script/generate migration add_adres_to_bedrijf adres:string

We geven hier in de naamgeving al aan wat we willen.

add_adres = voeg column adres toe aan table bedrijfs van het type string.

En dat levert de volgende migration op.


yaml


En dan is het weer het bekende commando.

> rake db:migrate

== BedrijvenAdresColumn: migrating ==

-- add_column(:bedrijfs, :adres, :string)

-> 0.0080s

== BedrijvenAdresColumn: migrated (0.0082s) ==

En de migration is weer uitgevoerd.

>> Bedrijf.column_names

=> [ "id", "naam", "plaats", "created_at", "updated_at" ]

>> reload!

Reloading...

=> { }

>> Bedrijf.column_names

=> [ "id", "naam", "plaats", "created_at", "updated_at", "adres" ]

En de adres column is toegevoegd.

En zo zijn er natuurlijk nog heel veel andere dingen te doen met migrations.

Rails maakt een schema_info table aan met een version column zodat we dat kunnen gebruiken om een rollback te doen. Dat doen we als volgt:

Omdat we twee migraties hebben aangemaakt is het mogelijk om terug te gaan naar versie één, wat neerkomt op het verwijderen van de adres column.

> rake db:migrate VERSION=1

== BedrijvenAdresColumn: reverting ==

-- remove_column(:bedrijfs, :adres)

-> 0.0781s

== BedrijvenAdresColumn: reverted (0.0782s) ==

En als het goed is moet de adres column weer verwijderd zijn.

LET OP: VERSION moet met hoofdletters anders werkt het niet.

>> Bedrijf.column_names

=> [ "id", "naam", "plaats", "created_at", "updated_at", "adres" ]

>> reload!

Reloading...

=> { }

>> Bedrijf.column_names

=> [ "id", "naam", "plaats", "created_at", "updated_at" ]

Er is nog veel meer te doen met migrations, maar dat laat ik aan de lezer over.


rails se !