Websiteentwicklung: Ruby on Rails: Datenbank und Model

Wie arbeiten Datenbank und Model zusammen?

Datenbank verändern mit Migrations Bearbeiten

Die Problemstellung Bearbeiten

Bei Web-Applikationen tritt folgendes Problem auf: im Laufe der Entwicklung ändert sich das Datenbank-Schema. Gleichzeitig ist die Applikation aber schon im Echt-Betrieb, man kann die Produktions-Datenbank nicht einfach löschen und von Grund auf neu bauen.

Es ist also notwendig, die Veränderungs-Schritte der Datenbank zu speichern, und auf allen Servern (verschiedene Entwicklungs-Rechner, Test, Produktion) in der gleichen Reihenfolge nachzuvollziehen.

Ruby on Rails bietet dafür eine Lösung: Migrations.

Eine Migration ist dabei ein Schritt der Veränderung - wobei dieser Schritt immer in beide Richtungen definiert ist.

Im Ordner /db/migrations/ sind die einzelnen Migrations gespeichert.

Nach der Erzeugung des scaffolds für hallo sieht das z.B. so aus:

 20090829142637_create_hallos.rb

Diese Datei enthält das Anlegen der Tabelle für das Model Hallo:

class CreateHallos < ActiveRecord::Migration
    def self.up
      create_table :hallos do |t|
	t.string :von
	t.text :meldung
	t.string :farbe
	t.timestamps
      end
    end
    def self.down
      drop_table :hallos
    end
  end


Eine Migration erstellen Bearbeiten

Mit dem Kommandozeilen-Befehl

 ↯rake db:migration↯
 rake db:migrate
 (siehe auch rake -T [korrigiert uwe.schimon@mailpost.de])

werden jeweils alle neuen Migrations ausgeführt. Mit

 rake db:rollback

kann der letzte Schritt rückgängig gemacht werden. Welcher Migrations-Schritt bereits angewandt wurde wird in der Datenbank salbst gespeichert, in der Tabelle schema_migrations

 

Wenn man die Datenbank verändern will - zum Beispiel um eine neue Spalte in die Tabelle einzufügen - so kann man selbst eine migration erzeugen:

 rails generate migration AddWiederholungToHallo wiederholung:integer

Aus der Namens-Konvention erzeugt der Generator gleich einen guten Entwurf für die Migration:


 class AddWiederholungToHallo < ActiveRecord::Migration
   def self.up
     add_column :hallos, :wiederholung, :integer
   end
   def self.down
     remove_column :hallos, :wiederholung
   end
 end

Was noch zu tun ist Bearbeiten

  Dazu gibt es einen Rails Guide [1] Migrations
  Siehe dazu die Rails API[2] ActiveRecord Migration


Nach dem Hinzufügen oder Löschen von Spalten aus der Tabelle muss das Model nicht verändert werden! Die Spalten werden automatisch als Attribute des Objekts übernommen. Der Controller muss meist auch nicht verändert werden.

Nur die Views (Eingabemasken, Anzeige des Objekts) müssen verändert werden!

Daten lesen und speichern mit dem Model Bearbeiten

Wir arbeitet das Model mit der Datenbank zusammen? Das werden wir nun interaktiv erforschen


Daten Suchen und Finden Bearbeiten

Es gibt eine interaktive Shell für Rails. Gestartet wird sie mit

 rails console

Nun kann man ruby-befehle eintippen und sieht sofort das Ergebnis.

   >> Hallo.find(1)
   => #<Hallo id: 1, von: "Brigitte", meldung: "Hallo Welt, es freut mich sehr Dich zu sehen!", farbe: "#FF0000", created_at: "2009-08-29 14:28:54", updated_at: "2009-08-29 14:28:54">

Die Klasse Hallo hat (wie jedes Klasse des Models) eine Methode find. Mit find(1) suche ich nach dem Objekt das in der Datenbank die id=1 hat.

Mit find(:all) suche ich nach allen Objekten. Das gibt viel output (hier gekürzt!)

   >> Hallo.find(:all)
   => [#<Hallo id: 1, von: "Brigitte">, #<Hallo id: 2, von: "Karin">, #<Hallo id: 3, von: "Hilmar">]
  

Daten anlegen Bearbeiten

Hier kann man auch neue Objekte anlegen:

   >> h = Hallo.new
   => #<Hallo id: nil, von: nil, meldung: nil, farbe: nil, created_at: nil, updated_at: nil>
   >> h.von = "Tippse"
   => "Tippse"
   >> h.meldung = "Auch ohne das Web kann ich einfügen"
   => "Auch ohne das Web kann ich einf\201gen"
   >> h
   => #<Hallo id: nil, von: "Tippse", meldung: "Auch ohne das Web kann ich einf\201gen", farbe: nil, created_at: nil, updated_at: nil>

das Objekt existiert derzeit nur im Hauptspeicher, im laufenden Programm - es ist noch nicht in der Datenbank gespeichert. (Deswegen hat es auch noch keine id). mit save kann ich versuchen das Objekt zu speichern:

   >> h.save
   => false

Der Rückgabewert false bedeutet: das Speichern hat nicht funktioniert. Warum? Weil die Farbe nicht gespeichert werden kann, ich habe ja eine Validierung auf dem Farb-Feld Programmiert:

  # im Model 
  validates_format_of :farbe, :with => /^#......$/,  :message => "nur Farb-Code mit # und 6 Stellen (hexadezimal) erlaubt" 

Also muss ich die Farbe korrekt setzen und kann dann speichern:

   >> h.farbe="#00FF00"
   => "#00FF00"
   >> h.save
   => true

Danach hat h auch eine id, und werte in created_at und updated_at:

   >> h
   => #<Hallo id: 7, von: "Tippse", meldung: "Auch ohne das Web kann ich einf\201gen", farbe: "#00FF00", created_at: "2009-08-31 11:46:06", updated_at: "2009-08-31 11:46:06">



Weitere Quellen Bearbeiten

  1. Rails Guide Migrations
  2. Rails API ActiveRecord Migration