Migration in Rails ist ein Konzept zur Entwicklung, Abstraktion und Dokumentation von Datenbankstrukturen. Der übliche Weg zur Entwicklung bzw. Definition eines Datenbankschema in MySQL ist die Nutzung der DDL (Data Definition Language) wobei man üblicherweise Anweisungen wie diese in einer Datei speicherte:
CREATE TABLE `sample` (
`id` INT NOT NULL AUTO_INCREMENT ,
`caption` VARCHAR( 255 ) NOT NULL ,
`description` TEXT NOT NULL ,
`position` INT NOT NULL ,
PRIMARY KEY ( `id` )
) TYPE = MYISAM ;
Diese Dateien werden dann (ggfls. mit DROP TABLE IF EXISTS) über den MySQL Client oder auch PhpMyAdmin in die Datenbank eingespielt. Ich selber habe in meinem alten Framework diese Änderungen in jeweils eine Datei pro Änderung gepackt und in das Subversion Repository eingepflegt. So hatten alle beiteiligten Programmierer die Möglich stets den aktuellen Stand der Datenbank nachzuvollziehen. Migrationen in Rails gehen da noch einen Schritt weiter, es gibt wie üblich einen Generator dem man die Verwaltung und Erzeugung der Migrationen anvertraut.
script/generate migration AddedUserTable
Rails erzeugt nun im Verzeichnis /db/migrate/ eine Datei mit dem Namen 001_added_user_table.rb. Die Datei hat folgenden Inhalt:
class AddedUserTable < ActiveRecord::Migration def self.up end def self.down end end
Um nun dem Namen der Klasse gerecht zu werden bestücken wir die Methode mit Code der eine User Tabelle erzeugt.
class CreateUsers < ActiveRecord::Migration
def self.up
create_table "users", :force => true do |t|
t.column :login, :string
t.column :email, :string
t.column :crypted_password, :string, :limit => 40
t.column :salt, :string, :limit => 40
t.column :created_at, :datetime
t.column :updated_at, :datetime
Es ist soweit. Die erste Microanwendung ist - Dank dem Scaffolder - in kürzester Zeit fertig und der nächste logische Schritt ist die Installation auf einem Server im Internet. Man will ja auch mal was zeigen können. Ich betreibe die meisten meiner Anwendungen auf einem FreeBSD Server und nutze dort natürlich PHP, MySQL und Apache. Für ein erstes Deployment sollte eine Installation von Rails und FastCGI ausreichen, obwohl ich gelesen habe das moderne Applikationen mittels Apache, FastCGI und einem Mongrel Cluster serviert werden. Das ist mir aber jetzt erstmal zu kompliziert.
Das eigentliche Installieren der benötigten Software ist zunächst unkompliziert, FastCGI, Ruby und Rails lassen sich ohne Schwierigkeiten über die Ports installieren. pkg_info | grep -i suchphrase hilft dabei die notwendigen Ports zu identifizieren. Wenn alles installiert ist muss der VirtualHost eingerichtet werden:
FastCgiServer "/www/application.de/public/dispatch.fcgi" -idle-timeout 60 -initial-env RAILS_ENV=development -processes 2
<virtualHost *:80>
DocumentRoot /www/application.de/public/
ServerName application.de
<Directory /www/application.de/public/>
Options +ExecCGI +FollowSymLinks
AllowOverride all
Allow from all
Order allow,deny
</Directory>
</VirtualHost>
Das interessante ist die lange Zeile die den eigentlichen Server definiert (FastCgiServer) und so elegant mein schönes Design zerlegt.
Mit Layout sind HTML Templates gemeint die als Container für die dynamisch erzeugten Inhalte dienen. Früher war es durchaus üblich eine HTML Seite die dynamisch erzeugt wird in drei oder mehr Teile zu zerlegen. Beispielsweise in Header, Footer und Content Templates. Heutzutage sind jedoch Layouts modern und tatsächlich sinnvoller, da die Templates mit <html> anfangen und mit </html> enden, was die Bearbeitung und Weiterentwicklung erleichtert.
Das arbeiten mit Layouts in Rails in einfach. Im Verzeichnis
/view/layouts
wird für jeden mit dem Scaffolder erzeugten Controller ein gleichnamiges Layout hinterlegt. Gibt es für einen Controller kein Layout wird automatisch ein Layout mit dem Name application.erb verwendet. Soll ein Controller ein bestimmtes Layout verwenden das weder mit dem Namen übereinstimmt noch das application.erb ist, kann im Controller mittels der layout Methode das Layout definiert werden.
class DomainController < ActionController::Base
layout "provider"
end
Schon vor zwei Jahren habe ich mit Rails experimentiert und dabei war es vor allem das Scaffolding das mich beeindruckt hat. Man erzeugt auf der Datenbank seine Strukturen, setzt den Scaffold Generator darauf an und bekommt voll funktionsfähige Seiten für die Verwaltung der Daten. Der Scaffolder legt Controller, Model, View und Testscripte an, so dass man sofort ein funktionierendes System hat.
Mit Version 2.0 hat Rails die Syntax des Scaffolders geändert. Man gibt jetzt nur noch den Modelnamen an und kann die einzelnen Felder des Model bzw. der Datenbanktabelle als Parameter in Form AttributeName:SQL_TYP angeben. Zur Zeit kann ich folgende SQL_TYPEN ermitteln
Mein Scaffold sieht ungefähr so aus
script/generate scaffold Domain domain:string provider_id:integer IP:string
Danach lasse ich den Rake Task
rake db:migrate;
laufen und Rails hat mir alles benötigte erzeugt, inklusive der Datenbanktabellen "domains" und "schema_info". Jetzt noch ein wenig in den Templates aufräumen und schon habe ich was zum vorzeigen. Das ist eine ganz neue Form der Produktivität...
Erzeugt man ein neues Projekt mit dem Aptana Project Wizard wird dieses leider wieder mit SQLite3 erzeugt und ist demnach für mich erstmal nicht nutzbar. Ein kurzer Blick in die Settings von Aptana und Rails in den Eclipse Preferences zeigt auch kein entsprechendes Feld dafür an. Ich vermute es muss eine allgemeine Rails Einstellung sein. Also mal recherchieren...
...nicht's zu finden, zumindest nicht in den ersten 5 Minuten und viel mehr Zeit möchte ich darauf nicht verwenden. Ich durchsuche noch die Dateien im Ruby Ordner, wo auch Rails gespeichert ist...und Voilá:
/ruby/lib/ruby/gems/1.8/gems/rails-2.0.2/lib/rails_generator/generators/applications/app/app_generator.rb
In Zeile 11:
default_options :db => (ENV["RAILS_DEFAULT_DATABASE"] || "sqlite3l"),
:shebang => DEFAULT_SHEBANG, :freeze => false
einfach sqlite3 durch mysql ersetzten und fortan erzeugt Rails neue Projekte mit MySQL.
default_options :db => (ENV["RAILS_DEFAULT_DATABASE"] || "mysql"),
:shebang => DEFAULT_SHEBANG, :freeze => false
Sicherlich keine Lösung für die Ewigkeit, aber die ersten SChmerzen sind erstmal beseitigt. Findet jemand einen eleganteren Weg freue ich mich über einen Kommentar oder eine Mail.
Also schnell die Datenbank Parameter in der Datei /config/databases.yml angepasst, das Projekt am noch mal erzeugt, WEBrick rebootet und weiter gehts. Als nächstes wird die Default Route angepasst, der Screen ist zwar chic aber nicht was ich benötige. Das Routing übernimmt die Datei /config/routes.rb und dort gibt es einen Eintrag:
# map.root :controller => "welcome"
Diesen passe ich auf meine Bedürfnisse an
map.root :controller => "index"
Wichtig ist natürlich den Hash # zu entfernen. Ich möchte einen "Index" Controller anlegen und dem entsprechend richte ich die Route ein.
Die Installation von Ruby On Rails ist wirklich einfach. Auf meiner Ubuntu Büchse war es einfach durch den Paketmanager APT zu installieren. Detaillierte Anweisung zum installieren unter Ubuntu finden sich hier: http://wiki.rubyonrails.org/rails/pages/RailsOnUbuntu
Als Entwicklungsumgebung wird an prominenten Stellen regelmäßig Aptana (http://www.aptana.com/) empfohlen, das eine Weiterentwicklung des früheren RadRails ist. Dabei handelt es in beiden Fällen um Eclipse Distibutionen bzw. Plugins. Leider verlief die Installation von Aptana unter nicht reibungslos, es fehlten RCP Plugins die durch den Eclipse Plugin Manager nicht zu beschaffen waren. da habe ich kurzerhand beschlossen das ganze auf Windows zu installieren.
Auch die Windows Installation verlief zunächst reibungslos. Zuerst Ruby installieren, dann RubyGems und danach dann mit RubyGems die eigentliche Rails Installation
gem install rails --include-dependencies
Die ganze Prozedur ist hier beschrieben http://rubyonrails.org/down
Als nächstes kann dann ein erstes Rails Projekt angelegt werden, doch Achtung! Führt man das Kommando wie auf der Rails Seite beschrieben aus, also
rails path/to/your/new/application
wird das Projekt mit SQLite3 angelegt. Wer es mag...? Möchte man sein Projekt mit MySQL betreiben lautet der Aufruf dazu
rails -d mysql path/to/your/new/application
Das erste Projekt ist nun eingerichtet, auf der Konsole sieht man das ein ganze Menge an Ordnern und Dateien eingerichtet wird und nun wird es spannend. Rails wird von Haus aus mit einem Webserver geliefert. Um diesen zu starten begibt man sich in dass Verzeichnis des neuen Projekts
cd /path/to/new/project/
führt dann
ruby script/server
aus.
Nun kann das Projekt im Browser betrachtet werden, dazu ruft man folgende Seite im Browser der Wahl auf:
http://localhost:3000