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 Buch 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


Rheinwerk Computing - Zum Seitenanfang

10.6 Suchen  Zur nächsten ÜberschriftZur vorigen Überschrift

kap_activerecord_suchen

find

Für die Suche wird die Klassen-Methode find auf ein ActiveRecord-Model angewendet. ActiveRecord kennt folgende Arten der Suche:

  • Suche nach einem oder mehreren Datensätzen über ihre ID
    Mit dem Aufruf Client.find(1) wird ein Objekt mit dem ersten Datensatz zurückgeliefert.
  • Suche nach dem ersten Datensatz, der bestimmte Kriterien erfüllt
    Client.find(:first) liefert ein Objekt mit dem ersten Datensatz zurück. Optional kann ein Suchkriterium und/oder die Sortierreihenfolge angegeben werden:
    Client.find(:first, :conditions => "firstname = 'William'")
  • Suche nach allen Datensätze, die bestimmte Kriterien erfüllen
    Client.find(:all) liefert eine Liste von Objekten aller Datensätze zurück. Bei dieser Suchvariante kann auch ein Suchkriterium und/oder eine Sortierreihenfolge angegeben werden:
    Client.find(:all, :order => "created_at DESC")
  • Suche mit dynamischen find-Methoden
    ActiveRecord bietet eine Kurzschreibweise für die Suche nach einem bestimmten Feld an (find_by_feldname). Um z. B. nach dem Vornamen eines Kunden zu suchen, kann man die Schreibweise Client. find_by_firstname("Hussein") verwenden.
  • Suche mit selbstdefinierten find-Methoden
    Sie können auch Ihre eigenen find-Methoden definieren, wie z. B. client.find_new_last_week, um alle neuen User, die seit der letzten Woche angelegt wurden, abzufragen.
  • Suche über SQL
    Sie können mit find_by_sql direkt SQL-Befehle an die Datenbank schicken. Wird in der Regel relativ selten verwendet.

Rheinwerk Computing - Zum Seitenanfang

Suche nach IDs  Zur nächsten ÜberschriftZur vorigen Überschrift

Primärschlüssel ID

Die einfachste Suche ist die Suche nach einer oder mehreren IDs. In ActiveRecord sollte jede Tabelle einen Primärschlüssel vom Typ Integer mit dem Feldnamen id besitzen. Wird eine Datenbanktabelle über eine Migration-Datei erzeugt, wird dieses Feld automatisch angelegt. Die ID wird von Rails automatisch verwaltet. Beim Einfügen eines neuen Datensatzes wird jeweils die nächsthöhere ID verwendet (auto increment). Jeder Datensatz besitzt also eine eindeutige ID.

In der Praxis verwenden Sie oft noch weitere Felder, um einen Datensatz eindeutig zu kennzeichnen. Dazu gehören z. B. Kundennummern, ISBN, Bestellnummern usw. Diese Felder können zusätzlich zu der ID in der Tabelle angelegt werden. Die Suche nach der ID, die im Folgenden beschrieben wird, sucht jedoch nur nach dem Feld id . Verwenden Sie für die Suche nach mehreren Feldern die Suche über alle Datensätze.

Zusammengesetzte Primärschlüssel
Zusammengesetzte Primärschlüssel werden in Rails nicht direkt unterstützt.

Die Suche nach einer ID liefert genau ein Objekt mit dem entsprechenden Datensatz zurück, wenn der Datensatz mit dieser ID existiert:

client = Client.find(1)
client.id
=> 1

Mehrere IDs

Um mehrere IDs zu suchen, werden einfach die entsprechenden IDs übergeben. Es ist auch erlaubt, die Werte in einem Array zu übergeben. Das Ergebnis ist das gleiche:

clients = Client.find(1,3)
clients.size
=> 2
clients.map(&:id)
=> [1,3]
clients = Client.find([1,3])
clients.size
=> 2
clients.map(&:id)
=> [1,3]

Der Ausdruck clients.map(&:id) ist eine Abkürzung für clients.map{|c| c.id\ }.

Laufzeitfehler, falls IDs nicht vorhanden
Wenn der gesuchte Datensatz bei der Suche nach einer ID nicht existiert, wird ein RecordNotFound-Laufzeitfehler generiert. Bei allen anderen Sucharten wird ein leeres Ergebnis (nil) zurückgeliefert.
client = Client.find(13)
=> ActiveRecord::RecordNotFound: Couldn't find Client
with ID=13
Der Fehler kann wie folgt abgefangen werden:
begin
  client = Client.find(13)
rescue ActiveRecord::RecordNotFound
# Der Code in diesem Bereich wird ausgeführt,
# wenn es zu einem Fehler gekommen ist.
end

Rheinwerk Computing - Zum Seitenanfang

Suche nach dem ersten Datensatz oder Ausgabe aller Datensätze  Zur nächsten ÜberschriftZur vorigen Überschrift

Sortierreihenfolge

Mit dem Aufruf find(:first) wird der erste Datensatz zurückgeliefert. Wenn keine Sortierreihenfolge oder kein Suchkriterium angegeben wurde, ist nicht klar, welcher Datensatz dann zurückgeliefert wird (in MySQL wird der Datensatz mit der kleinsten ID zurückgegeben). Deshalb ist es empfehlenswert, eine Sortierreihenfolge anzugeben. Im folgenden Fall wird der Datensatz mit der kleinsten ID ausgegeben:

client = Client.find(:first, :order=>"id")
client.id
=> 1

Der Aufruf find(:all) liefert ein Array aller Datensätze:

clients = Client.find(:all)
clients.size
=> 3
clients.map(&:firstname)
=> ["William", "Kara", "Lee"]

Richtig interessant wird es erst, wenn die Suche mittels Suchkriterien eingeschränkt wird.

Wie das letzte Element ermitteln?
Das letzte Element kann einfach ermittelt werden, indem man die Sortierreihenfolge umkehrt. Um z. B. den zuletzt eingefügten Datensatz zu ermitteln (der Datensatz mit der höchsten ID), geben Sie die Sortierreihenfolge absteigend :order => " id DESC" statt aufsteiegend :order =>" id" an.
client = Client.find(:first, :order=>"id DESC")
client.id


Rheinwerk Computing - Zum Seitenanfang

Suchoptionen im Überblick  Zur nächsten ÜberschriftZur vorigen Überschrift

Es gibt eine Menge von optionalen Parametern, die für find(:first) und find(:all) verwendet werden können:

  • :conditions
    Gibt ein Suchkriterium an.
  • :order
    Gibt an, nach welchen Feldern sortiert werden soll.
  • :group
    Hiermit können Gruppierungen durchgeführt werden.
  • :limit
    Beschränkt die Anzahl der Suchergebnisse.
  • :offset
    Gibt an, ab welchem Datensatz die Ergebnisse zurückgeliefert werden sollen.
  • :joins
    Entspricht dem Join-SQL-Befehl. Kommt eher selten zum Einsatz, da Joins automatisch von ActiveRecord durchgeführt werden.
  • :include
    Hiermit können assoziierte Tabellen angegeben werden, die beim Generieren der Ergebnisobjekte gleich mitgeladen werden.
  • :select
    Hiermit kann man angeben, welche Felder in den Suchergebnissen enthalten sein sollen. Der Standardwert ist * , was allen Feldern entspricht. Um nur die Felder firstname und lastname in den Suchergebnissen zu berücksichtigen, muss :select auf 'firstname, lastname' gesetzt werden.
  • :from
    Gibt an, in welcher Tabelle gesucht werden soll. Wird von ActiveRecord automatisch gesetzt.
  • :readonly
    Wenn diese Option auf true gesetzt wird, können die Suchergebnisse nicht verändert werden.
  • :lock
    Dient zum Sperren einer Tabelle.

Es können mehrere Optionen, wie im folgenden Beispiel gezeigt, gleichzeitig verwendet werden:

Client.find(
  :all,
  :conditions =>   :lastname=>"Adama"},
  :limit => 10,
  :order =>"firstname"
)

Rheinwerk Computing - Zum Seitenanfang

Suchbedingung (:conditions)  Zur nächsten ÜberschriftZur vorigen Überschrift

Meistverwendete Suchoption

Die meistverwendete Suchoption ist :conditions, mit der die Suchbedingung angegeben wird. Die Suchbedingung kann in drei Formaten angegeben werden:

  • SQL-Zeichenkette
    z. B. Client.find(:all, :conditions => "firstname = 'Lee'")
  • SQL-Array
    z. B. Client.find(:all, :conditions => ["firstname = ?",    'Lee'])
  • Hash
    z. B. Client.find(:all, :conditions => [:firstname => 'Lee' ])

Im Folgenden werden die verschiedenen Formate in den Suchbedingungen näher beschrieben:

:conditions mit SQL-Zeichenkette

Client.find(:all, :conditions =>
"lastname = 'Adama' AND birthday > '1950-01-01'")

Die Bedingung wird von Rails unverändert in die WHERE -Klausel des SQL-Befehls, der intern ausgeführt wird, übernommen:

SELECT * FROM clients
WHERE lastname = 'Adama' AND birthday > '1950-01-01'

Sicherheit

Deshalb ist Vorsicht geboten, insbesondere dann, wenn Sie Variablen aus Benutzereingaben einsetzen(siehe Kapitel 17).

lastname = "Adama"
firsname =
Client.find(
  :all,
  :conditions => "lastname = '#lastname'
		  AND birthday > '#birthday'")

Außerdem werden die Variablen gegebenenfalls nicht in den richtigen Typ umgewandelt.

Sicherheitshinweis zu SQL-Injection
Vermeiden Sie die Verwendung der SQL-Zeichenkette in :conditions , wenn Sie Variablen einsetzen. Es könnten per SQL-Injection unerlaubte SQL-Befehle ausgeführt werden. Verwenden Sie deshalb in diesen Fällen das SQL-Array oder einen Hash in :conditions . Mehr zum Thema Sicherheit erfahren Sie in Kapitel 17

:conditions mit SQL-Array

lastname = "Adama"
birthday = Date.new(1950,1,1)
Client.find(
  :first,
  :conditions =>
  ["lastname= ? AND birthday > ?", lastname, birthday])

Alternativ:

Client.find(
  :first,
  :conditions =>
    ["lastname= :lname AND birthday > :bday ",
    :lname => "Adama" , :bday => Date.new(1950,1,1)])

ActiveRecord führt Folgendes automatisch durch:

  • Automatische Umwandlung der Datentypen
    Zum Beispiel wird der Ruby-Typ Date automatisch in den Datumstyp umgewandelt, der in SQL erwartet wird.
  • Zeichenketten werden automatisch in Hochkommas gesetzt
    Bei der Verwendung einer SQL-Zeichenkette müssen Zeichenketten manuell mit Hochkommas umschlossen werden:
    :conditions=>"lastname = 'Adama'"
    Wenn Sie ein SQL-Array oder einen Hash übergeben, übernimmt ActiveRecord das:
    :conditions=>[:lastname => var]
  • Unerlaubte Zeichen werden geschützt ausgegeben
    Unerlaubte Zeichen wie Hochkammas in den Variablen werden automatisch geschützt, um Sicherheitsprobleme z. B. durch eine SQL-Injection zu vermeiden.

:conditions mit Hash

Auf Gleichheit prüfen

Diese Variante ist sehr praktisch, wenn auf Gleichheit geprüft wird. In einem Hash werden die Werte den Feldnamen zugeordnet. Die einzelnen Zuweisungen werden im daraus generierten SQL-Code jeweils mit AND verbunden.

Client.find(:first, :conditions => {:firstname =>'Lee',
				    :lastname => 'Adama'}

Diese Variante ist genauso sicher wie die Übergabe eines SQL-Arrays.


Rheinwerk Computing - Zum Seitenanfang

Sortierreihenfolge (:order)  Zur nächsten ÜberschriftZur vorigen Überschrift

Suchergebnisse werden standardmäßig aufsteigend sortiert. Das heißt, es ist nicht erforderlich, die Sortierreihenfolge anzugeben, wenn Sie Ihr Ergebnis aufsteigend sortieren möchten:

clients = Client.find(:all, :order=>"firstname")

clients.map(&:firstname)
=> ["Kara", "Lee", "William"]

DESC

Um das Suchergebnis absteigend zu sortieren, müssen Sie die Sortierreihenfolge angeben:

clients = Client.find(:all, :order=>"firstname DESC")

clients.map(&:firstname)
=> ["Kara", "Lee", "William"]

ASC

Für eine aufsteigende Sortierung können Sie auch die Reihenfolge ASC angeben.

Es sind auch zusammengesetzte Sortierreihenfolgen möglich. Im folgenden Beispiel soll nach dem Nachnamen sortiert werden. Falls gleiche Nachnamen vorkommen, wird der jüngere Datensatz zuerst gelistet.

clients = Client.find(:all,
		      :order=>"lastname ASC, birthday DESC")
clients.map(&:firstname)
=> ["Lee","William","Kara"]
Wie die Sortierung funktioniert
Die Zeichenkette, die Sie in der Option :order angeben, wird als SQL-Fragment direkt bei ORDER BY angefügt. Deshalb können Sie im Prinzip alles angeben, was Ihr Datenbanksystem an der Stelle ORDER BY erlaubt.

Rheinwerk Computing - Zum Seitenanfang

Limitieren der Suchergebnisse  Zur nächsten ÜberschriftZur vorigen Überschrift

:limit

Mit :limit kann die Anzahl der Suchergebnisse eingeschränkt werden.

Um z. B. die ersten 10 Datensätze zu ermitteln, können Sie :limit wie folgt einsetzen:

clients = Client.find(:all, :limit => 10)
clients.size
=> 10

Wenn es weniger Datensätze gibt, als mit der Option :limit angegeben wurde, werden alle verfügbaren Datensätze zurückgeliefert. Es kommt also zu keinem Fehler.

:offset

Mit :offset kann die Position, ab der die Suchergebnisse angezeigt werden sollen, angegeben werden. Die Zählung beginnt dabei bei 0, das heißt, um z. B. beim dritten Datensatz zu beginnen, muss :offset auf 2 gesetzt werden.

clients = Client.find(:all, :offset => 2)

clients.map(&:id)
=> [3,4,5,...]

Kombination

Besonders nützlich ist die Kombination von :limit und :offset.

Sie wird oft für die Anzeige von Suchergebnissen verwendet, wenn zum Beispiel nur eine bestimmte Anzahl von Ergebnissen pro Seite angezeigt werden soll.

Um zum Beispiel die dritte Seite von Suchergebnissen zu zeigen, wenn 10 Ergebnisse pro Seite angezeigt werden, kann man wie folgt vorgehen:

clients = Client.find(:all, :offset => 30, :limit => 10 )

clients.map(&:id)
=> [31,32,33,...40]
:offset nur in Kombination mit :limit
Wenn :offset ohne :limit verwendet wird, wird das von ActiveRecord nicht beachtet. Die Option :limit kann hingegen allein verwendet werden.


Rheinwerk Computing - Zum Seitenanfang

Suche mit dynamischen Find-Methoden  Zur nächsten ÜberschriftZur vorigen Überschrift

In vielen Fällen kann auf die Angabe einer Suchbedingung mit Hilfe der Option :conditions verzichtet werden.

find_by_feldname

Für jedes Feld einer Tabelle steht die Methode find_by_feldname(wert) zur Verfügung, um nach dem entsprechenden Feld zu suchen. Der Befehl

Product.find_by_name("iPod")
gibt beispielsweise den ersten Datensatz zurück, dessen Name mit »iPod« übereinstimmt.

Um alle Datensätze zurückzuliefern, die mit dem gesuchten Wert übereinstimmen, kann die Methode find_all_by_feldname(wert) verwendet werden:

Product.find_all_by_name(" iPod")

Es sind auch Verknüpfungen mit and möglich:

Product.find_by_name("iPod")
# entspricht Product.find(:first, :conditions => "iPod")

Product.find_all_by_name("iPod")
# entspricht Product.find(:all, :conditions => "iPod")

Product.find_all_by_name_and_price("iPod",149)
# entspricht Product.find(:all, :conditions =>
# ["name = ? AND price = ?", 'iPod',149])

Dynamisch

Diese Find-Methoden werden als dynamisch bezeichnet, weil sie erst beim ihrem Aufruf zur Laufzeit erzeugt werden.

Es ist auch möglich, mit dieser Technik neue Objekte zu erstellen. Mit der Methode find_or_create_by_feldname(wert) wird zunächst eine Suche nach dem entsprechenden Feld durchgeführt. Ist die Suche erfolgreich, wird das entsprechende Objekt zurückgeliefert. Wird kein Datensatz gefunden, wird ein neues Objekt mit dem Wert erstellt.

product = Product.find_or_create_by_name("iPod")
# entspricht product = Product.find("iPod")
# oder product = Product.create(:name => "iPod")
# je nachdem, ob das Objekt gefunden wurde oder nicht

Wenn das Objekt jedoch noch nicht gespeichert werden soll, kann die Methode find_or_initialize_by_feldname(wert) verwendet werden:

product = Product.find_or_initialize_by_name("iPod")
# entspricht product = Product.find("iPod")
# oder product = Product.new(:name => "iPod")
# je nachdem, ob das Objekt gefunden wurde oder nicht

Rheinwerk Computing - Zum Seitenanfang

Suche über SQL  topZur vorigen Überschrift

find_by_sql

ActiveRecord erlaubt es auch, den SQL-Code direkt für die Suche anzugeben. Dies sollte in der Praxis jedoch nur in Ausnahmefällen erfolgen. Aus Performance-Gründen kann es sinnvoll sein, spezielle SQL-Befehle einzusetzen, die das Datenbanksystem bietet.

Im folgenden Beispiel wird der SQL-Befehl SOUNDS LIKE verwendet, der auch Suchergebnisse findet, die zwar von der Schreibweise verschieden sind, aber ungefähr gleich ausgesprochen werden. Dieser SQL-Befehl kann nur bei Verwendung einer MySQL-Datenbank benutzt werden.

Listing  Beispiel für find_by_sql

Product.find_by_sql(
  "SELECT trim(name) AS name, price
   FROM products
   WHERE name SOUNDS LIKE 'ball'")

Product.find_by_sql(
  "SELECT trim(name) AS name, price
   FROM products
   WHERE name SOUNDS LIKE ?",  'ball')


Ihre Meinung

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.

 <<   zurück
  Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: Ruby on Rails 2
Ruby on Rails 2
Jetzt Buch bestellen
 Ihre Meinung?
Wie hat Ihnen das Openbook gefallen?
Ihre Meinung

 Buchtipps
Zum Rheinwerk-Shop: Ruby on Rails 3.1






 Ruby on Rails 3.1


Zum Rheinwerk-Shop: Responsive Webdesign






 Responsive Webdesign


Zum Rheinwerk-Shop: Suchmaschinen-Optimierung






 Suchmaschinen-
 Optimierung


Zum Rheinwerk-Shop: JavaScript






 JavaScript


Zum Rheinwerk-Shop: Schrödinger lernt HTML5, CSS3 und JavaScript






 Schrödinger lernt
 HTML5, CSS3
 und JavaScript


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
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.


Nutzungsbestimmungen | Datenschutz | Impressum

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

Cookie-Einstellungen ändern