Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Geleitwort des Fachgutachters
Einleitung
1 Einführung
2 Installation
3 Erste Schritte
4 Einführung in Ruby
5 Eine einfache Bookmarkverwaltung
6 Test-Driven Development
7 Rails-Projekte erstellen
8 Templatesystem mit ActionView
9 Steuerzentrale mit ActionController
10 Datenbankzugriff mit ActiveRecord
11 E-Mails verwalten mit ActionMailer
12 Nützliche Helfer mit ActiveSupport
13 Ajax on Rails
14 RESTful Rails und Webservices
15 Rails mit Plug-ins erweitern
16 Performancesteigerung
17 Sicherheit
18 Veröffentlichen einer Rails-Applikation auf einem Server
Ihre Meinung?

Spacer
 <<   zurück
Ruby on Rails 2 von Hussein Morsy, Tanja Otto
Das Entwickler-Handbuch
Buch: Ruby on Rails 2

Ruby on Rails 2
geb., mit DVD
699 S., 39,90 Euro
Rheinwerk Computing
ISBN 978-3-89842-779-1
Online bestellenPrint-Version jetzt bestellen
* versandkostenfrei in (D) und (A)
Pfeil 10 Datenbankzugriff mit ActiveRecord
  Pfeil 10.1 Einführung
  Pfeil 10.2 Eine ActiveRecord-Model-Klasse generieren
  Pfeil 10.3 Rake-Tasks zum Verwalten von Datenbanken
  Pfeil 10.4 Getter- und Setter-Methoden
  Pfeil 10.5 Erstellen, bearbeiten und löschen
  Pfeil 10.6 Suchen
  Pfeil 10.7 Datenbankschema und Migrations
  Pfeil 10.8 Migration-Skripte
  Pfeil 10.9 Migration-Befehle im Detail
  Pfeil 10.10 Assoziationen
  Pfeil 10.11 Validierung
  Pfeil 10.12 Statistische Berechnungen
  Pfeil 10.13 Callbacks
  Pfeil 10.14 Vererbung

10 Datenbankzugriff mit ActiveRecord

ActiveRecord oder wie man Daten aus einer Datenbank wie Objekte behandelt.

Domain Specific Language

ActiveRecord ist ein Framework, das als domänenspezifische Programmiersprache (Domain Specific Language, DSL), d. h. als problemorientierte Programmiersprache, die nur einen bestimmten fachlichen Bereich unterstützt, den objektorientierten Zugriff auf relationale Datenbanksysteme wie MySQL, PostgreSQL, Oracle usw. steuert. Da es sich um ein eigenes Framework handelt, können Sie ActiveRecord auch außerhalb von Rails nutzen, aber dazu später mehr.


Rheinwerk Computing - Zum Seitenanfang

10.1 Einführung  Zur nächsten ÜberschriftZur vorigen Überschrift

Entwurfsmuster

Den Begriff ActiveRecord hat Martin Fowler in seinem Buch Patterns für Enterprise Application-Architekturen zur Benennung eines Entwurfsmusters (Desgin Pattern) zur Abbildung von objektorientierten Daten auf relationale Daten und umgekehrt verwendet.

Abbildung  Model-View-Controller Entwurfsmuster

Martin Fowler hält das ActiveRecord-Framework in Rails für die beste Implementierung des Entwurfsmusters. Nach seiner Definition ist ActiveRecord Folgendes:

Ein Objekt, das eine Zeile in einer Datenbanktabelle oder in einer Sicht umhüllt, die Datenbankzugriffe kapselt und Domänenlogik zu diesen Daten hinzufügt. Das hört sich etwas kompliziert an, ist aber im Prinzip ganz einfach.

Models

Angenommen, wir haben eine Datenbank mit den Tabellen products und clients zur Verwaltung von Produkten und Kunden. Zu jeder Tabelle gibt es jeweils eine entsprechende ActiveRecord-Klasse, die Models. Die Models sind für die Datenbankoperationen zuständig. In unserem Fall heißen die beiden Models Product und Client . Nach einer Konvention in Rails werden Tabellennamen mit Kleinbuchstaben und im Plural benannt und die Klassennamen im Singular mit einem führenden Großbuchstaben.

Abbildung  Jede Klasse entspricht einer Tabelle.

Jede Zeile in der Tabelle products wird durch ein Objekt bzw. eine Instanz der ActiveRecord-Klasse Product repräsentiert.

Abbildung  Jedes Objekt entspricht einer Zeile.

Klassen-Methoden

Jede ActiveRecord-Klasse besitzt u. a. folgende (Klassen-)Methoden:

  • new(...)
    Erzeugt ein neues ActiveRecord-Objekt (wird nicht gespeichert).
  • create(...)
    Dient zum Erzeugen eines ActiveRecord-Objekts und anschließendem Speichern in der Datenbank.
  • find(2)
    Mit Angabe einer ID wird der Datensatz mit dieser ID als ActiveRecord-Objekt zurückgeliefert.
  • find(:all, :conditions=>...)
    Zum Suchen von Daten. Das Ergebnis ist ein Array von ActiveRecord-Objekten.

Es ist auch möglich, eigene Methoden hinzuzufügen, wie z. B. eine Methode best_offer, die das günstigste Produkt aus der Produkt-Tabelle zurückliefert.

Jedes ActiveRecord-Objekt besitzt mindestens folgende Operationen:

  • save
    zum Speichern eines Objekts in der Datenbank.
  • update
    zum Ändern von allen oder einzelnen Attributen des Objekts.
  • destory, delete
    zum Löschen eines Objekts.

Rheinwerk Computing - Zum Seitenanfang

Vor- und Nachteile  Zur nächsten ÜberschriftZur vorigen Überschrift

Interessante Funktion

ActiveRecord bietet folgende sehr interessante Funktionen an:

  • Validierung
    Zu jedem Attribut kann man Validierungs-Regeln angeben, die festlegen, welchen Kriterien das Attribut entsprechen muss. Zum Beispiel kann man vorgeben, welche Attribute einen Werte haben müssen oder dass nur positive Zahlen erlaubt sind. Erst wenn alle Validierungs-Regeln erfüllt sind, kann das Objekt in der Datenbank gespeichert werden.
  • Before- und After-Filter
    Filter erlauben dem Entwickler, bestimmte Befehle vor oder nach dem Speichern eines Objekts durchzuführen. Zum Beispiel kann vor dem Speichern ein Feld automatisch aktualisiert werden.
  • Assoziation bzw. Relationen
    Auf sehr einfache Weise können Relationen, wie z. B. 1:n-Relationen, n:m-Relationen usw. zwischen den Model-Klassen abgebildet werden.
  • Migrations
    Mit Migrations ist es möglich, die Tabellenstruktur in Ruby zu beschreiben und auch Änderungen vorzunehmen wie z. B. das Hinzufügen oder Löschen von Spalten.
  • Automatische Attribute created_at und updated_at
    Wenn sich in der Tabelle die Felder created_at (oder created_on ) und updated_at (oder updated_on ) vom Datentyp DateTime befinden, werden sie automatisch aktualisiert.
  • Single Table Inheritance
    ActiveRecord unterstützt auch das Vererben von Models mit der Technik Single Table Inheritance.
  • Transaktionen
    Eine Transaktion gewährleistet, dass eine Gruppe von Datenbankoperationen gemeinsam ausgeführt werden, oder eben nicht, falls eine Operation scheitert.

Solange man sich auf Schienen bewegt, d. h. die Konvention von ActiveRecord beachtet, ist der Einsatz von ActiveRecord relativ leicht. Abweichungen von dem Standard sind meist nicht leicht umzusetzen. Folgendes wird in ActiveRecord nicht direkt unterstützt bzw. ist nicht so leicht zu realisieren:

  • Stored Procedures
  • Views
  • zusammengesetzte IDs
  • Abweichung von der Namenskonvention

Rheinwerk Computing - Zum Seitenanfang

Unterstützte Datenbanksysteme  Zur nächsten ÜberschriftZur vorigen Überschrift

Relationale Datenbanksysteme

Rails unterstützt die folgenden relationalen Datenbanksysteme (Relational Database Management Systems):

  • DB2
    DB2 ist ein kommerzielles Datenbanksystem von IBM.
  • Firebird
    Firebird ist die Open-Source Variante des kommerziell von Borland vertriebenen Datenbanksystems InterBase.
  • Frontbase
    Frontbase ist ein kommerzielles Datenbanksystem für Mac OS X.
  • MySQL
    MySQL ist das meistverwendete Open-Source-Datenbanksystem.
  • Openbase
    Openbase ist ein kommerzielles Datenbanksystem für Mac OS X.
  • Oracle
    Das leistungsfähige, kommerzielle Datenbanksystem Oracle ist leider nicht für Mac OS X verfügbar.
  • PostgreSQL
    Das Open-Source-Datenbanksystem PostgreSQL kann auch für Geschäftsanwendungen eingesetzt werden.
  • SQLite
    SQLite kommt ohne Datenbankserver aus. Es ist nur für kleine Applikationen oder Applikationen mit mehr Lesezugriffen als Schreibzugriffen geeignet. Beim Generieren des Rails-Projekts wird automatisch die Datenbankdatei development.sqlite3 im Verzeichnis db erstellt.
  • Sybase
    Sybase ist ein kommerzielles Datenbanksystem von einem der größten unabhängigen Softwarehäusern der Welt.

Rheinwerk Computing - Zum Seitenanfang

Ein erstes Beispiel  Zur nächsten ÜberschriftZur vorigen Überschrift

Wir werden im Folgenden ein kleines Beispielprojekt erstellen, um die grundlegende Funktionsweise von ActiveRecord zu erklären. Dabei werden wir zunächst keine Generatoren verwenden, sondern alles manuell erstellen, damit Sie die Funktionsweise besser nachvollziehen können. In der Praxis sollten Sie jedoch Generatoren einsetzen.

MySQL oder SQLite

Als Datenbanksystem setzen wir MySQL ein. Sollte auf Ihrem System nicht MySQL installiert sein, so lassen Sie einfach die Option --database beim Generieren des Rails-Projekts weg. Standardmäßig wird dann SQLite verwendet.

Projekt generieren

Zunächst erstellen wir ein neues Beispielprojekt activerecord_bsp1 und wechseln in das Projektverzeichnis.

rails activerecord_bsp1 --database=mysql

cd activerecord_beispiel

database.yml

Beim Generieren des Projekts wurde u. a. die Datenbank-Konfigurationsdatei config/database.yml automatisch erzeugt. Dieser Datei können Sie die Namen der erwarteten Datenbanken entnehmen.

...
development:
  adapter: mysql
  encoding: utf8
  database: activrecord_bsp1_development
  username: root
  password:
  socket: /tmp/mysql.sock

test:
  adapter: mysql
  encoding: utf8
  database: activrecord_bsp1_test
  username: root
  password:
  socket: /tmp/mysql.sock

production:
  adapter: mysql
  encoding: utf8
  database: activrecord_bsp1_production
  username: root
  password:
  socket: /tmp/mysql.sock

development

Für uns ist zunächst nur die Umgebung development relevant. Legen Sie gegebenenfalls einen Usernamen und ein Passwort an, falls Ihre Datenbank passwortgeschützt sein soll.

Datenbank erstellen

rake db:create

Anschließend erstellen wir eine Datenbank mit dem Namen, der in der Datei config/database.yml für die Umgebung development definiert ist. In Rails 2 muss die Datenbank nicht mehr manuell angelegt werden, sondern es steht ein Rake-Task zur Verfügung:

Listing  Erstellen einer Datenbank

rake db:create

Die Datenbank muss für alle Datenbanksysteme außer SQLite erstellt werden. Für SQLite wird beim Erstellen des Projekts die SQLite-Datenbank-Datei, in der die gesamte Datenbank gespeichert wird, automatisch angelegt.

Model erstellen

Wir legen nun die ActiveRecord-Klasse Product an. Dazu erstellen wir die Datei product.rb im Verzeichnis app/models mit folgendem Inhalt:

class Product < ActiveRecord::Base
end

Die Klasse Product scheint über keine Methoden zu verfügen, aber da sie von der Klasse Base innerhalb des Moduls ActiveRecord erbt, stehen ihr alle Methoden der Klasse Base zur Verfügung. ActiveRecord analysiert beim Laden der Klasse, welche Felder die Tabelle products enthält, und generiert dynamisch die Methoden, um auf die Felder zugreifen zu können. Zum Beispiel die Methode price, mit der der Preis eines Product-Objekts abgefragt werden kann.


Rheinwerk Computing - Zum Seitenanfang

Tabelle erstellen  topZur vorigen Überschrift

Nachdem wir die Datenbank und die Model-Klasse erstellt haben, müssen wir nun die zugehörige Datenbanktabelle products anlegen.

Konvention

Wir haben nirgendwo definiert, dass sich die Klasse Product auf die Tabelle products bezieht. Müssen wir auch nicht. Rails folgt der Konvention, dass Datenbanktabellen nach den zugehörigen Klassen im Plural benannt werden.

Die Tabelle products soll folgende Felder besitzen:

  1. Id
    Primärschlüssel der Tabelle vom Typ Integer
  2. Name
    Name des Produkts vom Typ Varchar(255)
  3. Price
    Preis des Produkts vom Typ Decimal mit 6 Stellen vor dem Komma und 2 Stellen nach dem Komma
  4. Enabled
    Dieses Feld gibt an, ob das Product freigegeben ist oder nicht, und ist deshalb vom Typ Boolean. Der Standardwert soll true sein.
  5. Created_at
    Erstellungsdatum des Datensatzes vom Typ Datetime
  6. Updated_at
    Änderungsdatum des Datensatzes vom Typ Datetime

Migration

Zum Anlegen der Tabelle werden wir eine sogenannte Migration-Datei einsetzen. Migration-Dateien enthalten Ruby-Code, in denen die Tabellenstruktur definiert wird. Für die Erstellung einer Migration stellt Rails den migration -Generator zur Verfügung. Wir werden die Migration-Datei jedoch von Hand erstellen, indem wir im Verzeichnis db das Unterverzeichnis migrate erzeugen und die Datei 001_create_products.rb darin erstellen.

Zusätzlich zur Tabellenstruktur werden wir in der Migration-Datei einige Beispieldatensätze definieren:

Listing  001_create_products.rb

class CreateProducts < ActiveRecord::Migration
  def self.up
    create_table :products do |t|
      t.string :name
      t.decimal :price, :precision => 8, :scale => 2
      t.boolean :enabled, :default => true
      t.timestamps
    end
    Product.create(:name => "iPod nano 3G", :price => 149.00)
    Product.create(:name => "Mac Book", :price => 1100.00)
  end

  def self.down
    drop_table :products
  end
end

Primärschlüssel

Das ID-Feld wird von ActiveRecord immer automatisch als Primärschlüssel vom Typ Integer angelegt, weshalb es nicht in der Migration definiert werden muss.

timestamps

Der Befehl timestamps erzeugt die Felder created_at und updated_at.

self.down

Wird eine Migration rückgängig gemacht, wird die Methode self.down ausgeführt. In unserem Beispiel wird dann die Tabelle products gelöscht.

Beispieldaten

Werden so wie in unserem Beispiel in der Migration-Datei auch Beispieldaten angelegt, wird bei Ausführung der Migration-Datei erst die Tabelle erstellt, und anschließend werden die Beispieldaten angelegt.

Die Migration wird mit folgendem Befehl aus dem Projektverzeichnis heraus ausgeführt:

Listing  Migration ausführen

rake db:migrate
== 1 CreateProducts: migrating ===========================
-- create_table(:products)
   -> 0.0046s
== 1 CreateProducts: migrated (0.0189s) ==================

Testen in der Konsole

Öffnen Sie zwei Terminalfenster, und wechseln Sie in das Projektverzeichnis. In einem Fenster starten Sie mit ruby script/server den lokalen Rails-Server. Hier können Sie später sehen, wie Rails arbeitet. In dem anderen Fenster starten Sie mit ruby script/console die Rails-Konsole.

count

In der Rails-Konsole können wir die neue ActiveRecord-Klasse nutzen, um z. B. die Anzahl der Produkte abzufragen:

>> Product.count
=> 2

In dem Fenster, in dem Sie den lokalen Rails-Server gestartet haben, können Sie u. a. sehen, welche SQL-Befehle Rails an die Datenbank sendet. Es wird u. a. Folgendes ausgegeben:

Product Columns (0.051914)   SHOW FIELDS FROM products
  SQL (0.050556)   SELECT count(*) AS count_all FROM products

Mit dem SQL-Befehl SHOW FIELDS FROM products erfragt Rails, aus welchen Feldern die Tabelle products besteht. Dies wird immer beim ersten Zugriff auf eine Tabelle durchgeführt.

Mit dem zweiten SQL-Befehl wird die Anzahl der Zeilen in der Tabelle bestimmt.

Gibt man in der Konsole nur den Klassennamen ein, so werden die Felder und deren Datentypen angezeigt.

>> Product
=> Product(id: integer, name: string, price: decimal,
created_at: datetime, updated_at: datetime)

Lesen und Ändern eines Datensatzes

find

Um ein Produkt aus der Datenbank auszulesen und zu verändern, können Sie folgende Befehle ausführen:

>> ipod = Product.find(1)
=> ...
>> puts ipod.name
=> iPod nano 3G
>> puts ipod.price
=> 149.0
>> ipod.price=139.0
=>...
>> ipod.save
=> true

Ausgabe in dem Fenster, in dem der lokale Rails-Server läuft:

SELECT * FROM products WHERE (products.`id` = 1)
BEGIN
UPDATE products SET "created_at" = '2008-01-24 22:16:33',
"name" = 'iPod nano 3G', "enabled" = 't', "price" = 139.0,
"updated_at" = '2008-01-24 22:30:45' WHERE "id" = 1
COMMIT

BEGIN und COMMIT sind Transaktionsbefehle, die dafür sorgen, dass entweder alle Befehle ausgeführt werden oder kein Befehl (falls es zu einem Problem kommt).

Erstellen eines neuen Datensatzes

new

Ein neues Produkt legen Sie wie folgt an:

>> imac = Product.new
=> ...
>> imac.name = 'iMac 24'
=> 'iMac 24'
>> imac.price = 1998.0
=> 1998.0
>> imac.save
=> true

create

Alternativ hätten wir auch die Kurzschreibweise zur Erzeugung eines neuen Produkts nutzen können:

Product.create(:name=>'iMac 24', :price=1998.0)

Die Befehle werden in folgenden SQL-Befehl umgewandelt:

BEGIN
INSERT INTO products ("name", "updated_at", "price", "enabled",
"created_at") VALUES('iMac 24', '2008-01-24 22:36:34', 1998.0,
't', '2008-01-24 22:36:34')
COMMIT

Die Methode create erlaubt es sogar, mehrere Datensätze auf einmal zu erzeugen, indem ein Array von Hashes als Parameter übergeben wird:

Product.create(
[:name => 'iMac 24', :price => 1998.0,
 :name => 'iPod nano 2G', :price => 139.0}
])

Suchen mit einem Kriterium

:conditions

Anschließend werden wir die billigsten Produkte suchen und ausgeben:

>>  cheapest = Product.find(:all,:conditions=>"price < 1500")
=> ...
>> cheapest.each {|prod| puts "Produkt #{prod.name} kostet
   #{prod.price} EUR"
Produkt iPod nano 3G kostet 139.0 EUR
Produkt Mac Book kostet 1100.0 EUR
=>...

Folgender SQL-Befehl wurde generiert:

SELECT * FROM products WHERE (price < 1500)

Löschen eines Datensatzes

destroy

Abschließend wollen wir noch den letzten Datensatz löschen:

>> Product.count
=> 3
>> macbook = Product.find(2)
=> ...
>> macbook.destroy
=> ...
>> Product.count
=> 2

Ausgabe SQL:

DELETE FROM products WHERE `id` = 2


Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen. >> Zum Feedback-Formular
 <<   zurück
  Zum Katalog
Zum Katalog: Ruby on Rails 2
Ruby on Rails 2
Jetzt bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Ruby on Rails 3.1






 Ruby on Rails 3.1


Zum Katalog: Responsive Webdesign






 Responsive Webdesign


Zum Katalog: Suchmaschinen-Optimierung






 Suchmaschinen-
 Optimierung


Zum Katalog: JavaScript






 JavaScript


Zum Katalog: Schrödinger lernt HTML5, CSS3 und JavaScript






 Schrödinger lernt
 HTML5, CSS3
 und JavaScript


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2008
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Rheinwerk Computing]

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de