Pizza on Rails. Frank Rothmann

Ähnliche Dokumente
Eine Anwendung mit InstantRails 1.7

Tutorial -

Objektorientierte Programmierung für Anfänger am Beispiel PHP

php Hier soll ein Überblick über das Erstellen von php Programmen gegeben werden. Inhaltsverzeichnis 1.Überblick Parameterübergabe...

Guide DynDNS und Portforwarding

Web-Kürzel. Krishna Tateneni Yves Arrouye Deutsche Übersetzung: Stefan Winter

mysql - Clients MySQL - Abfragen eine serverbasierenden Datenbank

Adminer: Installationsanleitung

Bauteilattribute als Sachdaten anzeigen

Einführung in die Java- Programmierung

Lokale Installation von DotNetNuke 4 ohne IIS

Artikel Schnittstelle über CSV

Durchführung der Datenübernahme nach Reisekosten 2011

Rails Ruby on Rails Ajax on Rails. Clemens H. Cap

Er musste so eingerichtet werden, dass das D-Laufwerk auf das E-Laufwerk gespiegelt

GITS Steckbriefe Tutorial

Universal Dashboard auf ewon Alarmübersicht auf ewon eigener HTML Seite.

SEMINAR Modifikation für die Nutzung des Community Builders

Datenbanksysteme SS 2007

Zugriff auf Daten der Wago über eine Webseite

OP-LOG

TYPO3 Super Admin Handbuch

INSTALLATION VON INSTANTRAILS 1.7

Mit der Maus im Menü links auf den Menüpunkt 'Seiten' gehen und auf 'Erstellen klicken.

Stellen Sie bitte den Cursor in die Spalte B2 und rufen die Funktion Sverweis auf. Es öffnet sich folgendes Dialogfenster

Kurzeinführung Excel2App. Version 1.0.0

Erweiterung der Aufgabe. Die Notenberechnung soll nicht nur für einen Schüler, sondern für bis zu 35 Schüler gehen:

Einfügen von Bildern innerhalb eines Beitrages

Binäre Bäume. 1. Allgemeines. 2. Funktionsweise. 2.1 Eintragen

Mediator 9 - Lernprogramm

Xcode/Cocoa/Objective-C Crashkurs Programmieren unter Mac OS X

Handbuch zur Anlage von Turnieren auf der NÖEV-Homepage

Installation des edu- sharing Plug- Ins für Moodle

M. Graefenhan Übungen zu C. Blatt 3. Musterlösung

Kapitel 3 Frames Seite 1

Java: Vererbung. Teil 3: super()

KURZANLEITUNG CLOUD OBJECT STORAGE

5.2 Neue Projekte erstellen

Dokumentation für das Spiel Pong

Inhalt. 1 Einleitung AUTOMATISCHE DATENSICHERUNG AUF EINEN CLOUDSPEICHER

Arbeiten mit UMLed und Delphi

In diesem Thema lernen wir die Grundlagen der Datenbanken kennen und werden diese lernen einzusetzen. Access. Die Grundlagen der Datenbanken.

Virtueller Seminarordner Anleitung für die Dozentinnen und Dozenten

Um ein solches Dokument zu erzeugen, muss eine Serienbriefvorlage in Word erstellt werden, das auf die von BüroWARE erstellte Datei zugreift.

Grundlagen der Informatik 2

In diesem Tutorial lernen Sie, wie Sie einen Termin erfassen und verschiedene Einstellungen zu einem Termin vornehmen können.

Professionelle Seminare im Bereich MS-Office

Lineargleichungssysteme: Additions-/ Subtraktionsverfahren

Facebook I-Frame Tabs mit Papoo Plugin erstellen und verwalten

Datenübernahme von HKO 5.9 zur. Advolux Kanzleisoftware

Einrichten des IIS für VDF WebApp. Einrichten des IIS (Internet Information Server) zur Verwendung von Visual DataFlex Web Applications

Erstellen eigener HTML Seiten auf ewon

Tutorial. In diesem Tutorial möchte ich die Möglichkeiten einer mehrspracheigen Web-Site erläutern.

PHP - Projekt Personalverwaltung. Erstellt von James Schüpbach

Diese Ansicht erhalten Sie nach der erfolgreichen Anmeldung bei Wordpress.

Objektorientierte Programmierung

Sich einen eigenen Blog anzulegen, ist gar nicht so schwer. Es gibt verschiedene Anbieter. ist einer davon.

Windows. Workshop Internet-Explorer: Arbeiten mit Favoriten, Teil 1

FTP-Server einrichten mit automatischem Datenupload für

How to install freesshd

Datenbanken für Online Untersuchungen

Anleitung zur Anmeldung beim EPA zur Nutzung von OPS 3.1

Kommunikations-Management

Ordner Berechtigung vergeben Zugriffsrechte unter Windows einrichten

HTML5 HOCKEYSTICK EXPANDABLE BANNER v1.0

Kostenstellen verwalten. Tipps & Tricks

Erstellen einer digitalen Signatur für Adobe-Formulare

Einstellungen im Internet-Explorer (IE) (Stand 11/2013) für die Arbeit mit IOS2000 und DIALOG

Folgende Einstellungen sind notwendig, damit die Kommunikation zwischen Server und Client funktioniert:

Funktionsbeschreibung Website-Generator

Handbuch Fischertechnik-Einzelteiltabelle V3.7.3

Kleines Handbuch zur Fotogalerie der Pixel AG

Legen Sie nun dieses Verzeichnis mit dem Namen "joomla" hier an: C:xampphtdocs.

KIP Druckerstatus Benutzerhandbuch KIP Druckerstatus Installations- und Benutzerhandbuch

Neue Schriftarten installieren

5 DATEN Variablen. Variablen können beliebige Werte zugewiesen und im Gegensatz zu

Es wird das Struts <html:option> Element erläutert und anhand von kleinen Beispielen der Umgang veranschaulicht.

Dokumentation IBIS Monitor

Hex Datei mit Atmel Studio 6 erstellen

Handbuch zum Excel Formular Editor

Das sogenannte Beamen ist auch in EEP möglich ohne das Zusatzprogramm Beamer. Zwar etwas umständlicher aber es funktioniert

.htaccess HOWTO. zum Schutz von Dateien und Verzeichnissen mittels Passwortabfrage

Erzherzog Johann Jahr 2009

2. Einrichtung der ODBC-Schnittstelle aus orgamax (für 32-bit-Anwendungen)

KeePass Anleitung. 1.0Allgemeine Informationen zu Keepass. KeePass unter Windows7

PHPNuke Quick & Dirty

Modul Bildergalerie Informationen zum Bearbeiten des CMS-Systems für den SV Oberteisendorf

HTML5. Wie funktioniert HTML5? Tags: Attribute:

Wordpress: Blogbeiträge richtig löschen, archivieren und weiterleiten

Leitfaden zur ersten Nutzung der R FOM Portable-Version für Windows (Version 1.0)

Individuelle Formulare

Contao für Redakteure

Anleitung über den Umgang mit Schildern

Schritt 1 - Registrierung und Anmeldung

Anleitung zur Webservice Entwicklung unter Eclipse

Kurzanleitung RACE APP

4D Server v12 64-bit Version BETA VERSION

Task: Nmap Skripte ausführen

Transkript:

Pizza on Rails Frank Rothmann

Inhaltsverzeichnis...1 1 Einführung...4 2 Ruby...5 2.1 Hello World...5 2.2 Kommentare...5 2.3 puts...5 2.4 Objektorientierung...6 2.4.1 Merkmale...6 2.4.2 Eisenbahn-Beispiel...6 2.5 Klassen...14 2.5.1 Attribute...15 2.5.2 Methoden...16 2.6Variablen...17 2.6.1 Zahlenwerte...18 2.6.2 String...19 2.6.3Boolean...20 2.6.4Array...20 2.6.5 Hash...21 2.6.6Symbol...21 2.6.7lokale Variablen...22 2.6.8Instanz-Variablen...22 2.6.9Class-Variablen...23 2.6.10Globale-Variablen...24 2.7 Schleifen...25 2.7.1 While / Until...25 2.7.2 each...26 2.8 Bedingungen...27 2.8.1 If.. then else...27 2.9 Blöcke...28 3 Rails unter der Lupe...29 3.1 Blog in 15 Minuten...29 3.2 Aufbau einer Rails Application...37 3.2.1Die Rails Komponenten...37 3.2.2 Skeletton...39 3.2.3 Controller...43 3.2.4 Model...50 3.2.5 View...51 Index-View...51 Edit-View...52 Show-View...53 4 Die Pizza App...54 4.1 Story...54 4.2 Pizzas...54 4.2.1 Scaffold...54 4.2.2 View...54 4.2.3 Controller...54 4.2.4 Model...54 4.3 Orders...54 4.3.1 Scaffold...54

4.3.2 View...54 4.3.3 Controller...54 4.3.4 Model...54

1 Einführung Die Intention ein Rails Tutorial zu schreiben rührt daher, dass ich seit einigen Jahren begeistert mit dem Rails-Framework Anwendungen entwickele. Rails hat sich durchaus als alltagstauglich erwiesen. Das Framework avanciert vielfach als eine Möglichkeit in kürzester Zeit eine Webapplication zu schreiben. Das ist zunächst einmal durchaus richtig, wenn man die Applikation jedoch mit mehr als den Grundfunktionen austatten möchte, kommt man über richtige Programmierung nicht umher. Aus diesem Grund habe ich dem eigentlichen Rails-Teil des Tutorial eine kurze Einführung in Ruby vorangestellt. Ein Grundverständnis der zugrunde liegenden Sprache halte ich für unumgänglich.

2 Ruby Die Programmiersprache Ruby wurde von dem japanischen Studenten Yukihiro Matz Matsumoto 1995 entwickelt. Die Programmiersprache sollte durchgängig objektorientiert sein, jedoch zunächst als Skriptsprache zu Verfügung gestellt werden. In den letzten Jahren entwickelte sich die Sprache massiv weiter, es kamen eine Vielzahl von Klassen hinzu, wodurch diese Sprache sich jetzt als objektorientierte Allroundsprache darstellt. Interpreter sind für die gängigen Betriebssysteme wie Windows, MacOS und Linux kostenlos erhältlich, zudem gibt es eine unter der JAVA-JVM laufende Variante JRUBY, die Ruby auf jeder JVM lauffähig macht. 2.1 Hello World Traditionsgemäß beginnt man einen Beitrag über eine Programmiersprache mit HelloWorld. Ich möchte hier keine Außnahme machen, daher hier das Beispiel: puts "Hello World" Wie man sieht besteht das Programm aus lediglich einer Zeile. Einfacher geht es nicht! 2.2 Kommentare Auch wenn unser HelloWorld keine Kommentare beinhaltet, möchte ich hier mit den Kommentare anfangen. Sie werden entweder als Zeilenkommentar gesetzt: # Hallo oder mit einem /# #/ umgeben: /# Hallo hier geht es weiter #/ 2.3 puts Der einzige Befehl in HelloWorld ist der puts Befehl. Mit ihm wird ein String ausgegeben. puts "Hello World" ergibt Hello World Pizza on Rails - 5 -

[Finished in 0.1s] 2.4 Objektorientierung Auch wenn bei dem HelloWorld-Beispiel nichts von Objektorientierung zu sehen war, handelt es sich bei Ruby um eine streng objektorientierte Sprache. Der Begriff Objektorientierte- Programmierung steht für einen sich von der herkömmlichen Programmierung grundsätzlich unterschiedlichen Ansatz. Ihn in vollem Umfang zu beschreiben würde ganze Bücher füllen, daher möchte ich hier auf das Wesentliche eingehen, was man zum Verständnis der Sprache Ruby und der Entwicklung mit Rails benötigt. Während man bei prozeduralen Sprachen grundsätzlich Aufgaben in Teilaufgaben unterteilt und diese dann programmiert, geht die objektorientierte Programmierung einen gänzlich anderen Weg. Hier beschreibt man ein Objekt durch eine Klasse in der man alle relevanten Attribute und alle diese Attribute veränderten Methoden definiert. Ein Programm besteht also aus einer Reihe unterschiedlicher, miteinander in Beziehung stehenden Klassen. 2.4.1 Merkmale Objekte sind grundsätzlich gekapselt! 2.4.2 Eisenbahn-Beispiel Den theoretischen Ansatz möchte ich durch ein kleines Beispiel verdeutlichen. Die Aufgabe besteht darin, ein Lokomotive zu programmieren. Eine Lokomotive wird programmiert, indem man die relevanten Eigenschaften in einer Klasse definiert. Gerade die Frage welche Eigenschaften relevant sind ist nicht unerheblich für die Komplexität des späteren Programms. Infrage kämen zunächst eine große Anzahl möglicher Attribute: Länge, Breite, Farbe, Höchstgeschwindigkeit, Gewicht.... Wir beschränken uns zunächst mal auf Attribute, die wir auch tatsächlich im Programm verwenden werden, in unserem Beispiel auf die Geschwindigkeit. 1!#/bin/ruby 2 class Lok 3 4 def initialize 5 @geschwindigkeit = 0 6 end 7 puts "Hallo" 8 9 10 end 11 12 emma = Lok.new 13 p emma Pizza on Rails - 6 -

Wir definieren zunächst eine Klasse Lok ( 2 10). Dazu definieren wir in Zeile 2 die Klasse und initialisieren diese mit der Methode initialize in Zeile 4 bis 6. Die Variable @geschwindigkeit setzen wir auf den Initialwert 0. Um zu sehen, dass wir die Klasse erstellt haben, geben wir mit dem Befehl puts in Zeile 7 Hallo aus. In Zeile 12 erstellen wir ein Objekt emma der Klasse Lok. Dieser Schritt ist wichtig. Die Klasse definiert die Eigenschaften und Methoden eines Objekts, durch die Methode.new wird aus der Klasse ein Objekt erstellt. Zeile 13 gibt mit dem Befehl p alle Objekteigenschaften des Objekts emma aus. Wenn wir das Programm starten ergibt sich: Hallo #<Lok:0x7f044a1c3590 @geschwindigkeit=0> [Finished in 0.0s] Neben der zu erwartenden Ausgabe Hallo wird die Klasse emma ausgegeben. Man sieht, dass es sich um ein Objekt vom de Klasse Lok handelt, dass in der Speicherstelle 0x7f044a1c3590 gebildet wurde und das einzige Merkmal @geschwindigkeit=0 besitzt. Pizza on Rails - 7 -

Nach dem ersten Erfolg erweitern wir die Klasse ein wenig: 1!#/bin/ruby 2 class Lok 3 4 def initialize 5 @geschwindigkeit = 0 6 end 7 8 9 def geschwindigkeit? 10 puts "Geschwindigkeit: #{@geschwindigkeit}" 11 end 12 13 end 14 15 emma = Lok.new 16 p emma 17 emma.geschwindigkeit? In den Zeilen 9 11 wird die Methode geschwindigkeit? definiert. Man benötigt sie, um auf die Variable @geschwindigkeit zugreifen zu können, da Klassen grundsätzlich gekapselt sind. Somit kann nur über definierte Methoden auf Variablen zugegriffen werden. Man spricht hier von einer sogenannten getter- Methode, die auf den Wert einer Variablen zugreift. Das in Zeile 15 erzeugte Objekt emma zeigt nun, wenn man die Methode geschwindigkeit? In Zeile 17 aufruft die die Geschwindigkeit an: Hallo #<Lok:0x7facb10ce1c0 @geschwindigkeit=0> Geschwindigkeit: 0 [Finished in 0.0s] Pizza on Rails - 8 -

Somit haben wir gerade die erste Eigenschaft objektorientierter Entwicklung kennengelernt: Objekte sind grundsätzlich gekapselt! Der Grund für die Kapselung von Objekten ist naheliegend. Da ein Programm aus vielen Objekten besteht, teilweise werden auch ganze Objekt-Bibliotheken importiert, ist es notwendig Objektinterna soweit wie möglich zu kapseln. Nur so können Seiteneffekte vermieden werden. Wir erweitern unsere Klasse um zwei weitere Methoden: 1!#/bin/ruby 2 class Lok 3 4 def initialize 5 @geschwindigkeit = 0 6 end 7 8 9 def beschleunige 10 @geschwindigkeit = @geschwindigkeit + 10 11 12 end 13 14 def bremse 15 @geschwindigkeit = @geschwindigkeit - 10 16 17 end 18 19 def geschwindigkeit? 20 puts "Geschwindigkeit: #{@geschwindigkeit}" 21 end 22 23 end 24 25 emma = Lok.new 26 p emma 27 emma.geschwindigkeit? 28 emma.beschleunige 29 emma.geschwindigkeit? 30 emma.bremse 31 emma.geschwindigkeit? #<Lok:0x7f5bc951d980 @geschwindigkeit=0> Geschwindigkeit: 0 Geschwindigkeit: 10 Geschwindigkeit: 0 [Finished in 0.0s] Die Methoden beschleunige und bremse wirken wie zu erwarten auf das Attribut geschwindigkeit. Attribute ( Objekteigenschaften) werden durch Variablen definiert Pizza on Rails - 9 -

Attribute werden durch Methoden beeinflusst Mit einer weiteren Erweiterung kann man den Methoden auch Werte übermitteln: 1!#/bin/ruby 2 class Lok 3 4 def initialize 5 @geschwindigkeit = 0 6 end 7 8 def beschleunige(wert) 9 @geschwindigkeit = @geschwindigkeit + wert 10 end 11 12 def bremse(wert) 13 @geschwindigkeit = @geschwindigkeit - wert 14 end 15 16 def geschwindigkeit? 17 puts "Geschwindigkeit: #{@geschwindigkeit}" 18 end 19 20 end 21 22 emma = Lok.new 23 p emma 24 emma.geschwindigkeit? 25 emma.beschleunige(20) 26 emma.geschwindigkeit? 27 emma.bremse(10) 28 emma.geschwindigkeit? #<Lok:0x7fa3fb8a5880 @geschwindigkeit=0> Geschwindigkeit: 0 Geschwindigkeit: 20 Geschwindigkeit: 10 Pizza on Rails - 10 -

Wir erweitern unser Bespiel ein letztes Mal zum Big Picture 1!#/bin/ruby 2 class Lok 3 4 def initialize 5 @geschwindigkeit = 0 6 end 7 8 def beschleunige(wert) 9 @geschwindigkeit = @geschwindigkeit + wert 10 end 11 12 def bremse(wert) 13 @geschwindigkeit = @geschwindigkeit - wert 14 end 15 16 def geschwindigkeit? 17 puts "Geschwindigkeit: #{@geschwindigkeit}" 18 end 19 20 end 21 22 class Elok < Lok 23 24 def initialize 25 super 26 @maxgeschwindigkeit = 320 27 @typ = "elok" 28 end 29 30 end 31 32 class Diesellok < Lok 33 34 def initialize 35 super 36 @typ = "Diesel-Lok" 37 @maxgeschwindigkeit = 320 38 @tankinhalt = 0 39 end 40 41 def tanken(wert) 42 @tankinhalt = @tankinhalt + wert 43 end 44 45 def tankinhalt? 46 puts "Tankinhalt: #{@tankinhalt}" 47 end 48 49 50 end Pizza on Rails - 11 -

51 emma = Lok.new 52 p emma 53 emma.geschwindigkeit? 54 emma.beschleunige(20) 55 emma.geschwindigkeit? 56 emma.bremse(10) 57 emma.geschwindigkeit? 58 59 fritzi = Elok.new 60 p fritzi 61 fritzi.beschleunige(180) 62 fritzi.geschwindigkeit? 63 fritzi.bremse(60) 64 fritzi.geschwindigkeit? 65 66 stinki = Diesellok.new 67 p stinki 68 stinki.beschleunige(130) 69 stinki.geschwindigkeit? 70 stinki.bremse(20) 71 stinki.geschwindigkeit? 72 stinki.tanken(200) 73 stinki.tankinhalt? Das Ergebnis: stinki = Diesellok.new p stinki stinki.beschleunige stinki.geschwindigkeit? stinki.bremse stinki.geschwindigkeit? stinki.tanken stinki.tankinhalt? Pizza on Rails - 12 -

Um das Programm zu verstehen, untersuchen wir es in mehreren Etappen. Wir haben jetzt erstmals Klassen gebildet, die alle Eigenschaften einer Elternklasse geerbt haben. Dies ist ein grundsätzliches Feature objektorientierter Entwicklung. 22 class Elok < Lok 23 24 def initialize 25 super 26 @maxgeschwindigkeit = 320 27 @typ = "elok" 28 end 29 30 end Zeile 22 beschreibt mit dem Zeichen <, dass die Klasse Elok alle Merkmale der Klasse Lok erbt. In Zeile 24-28 erweitern wir die Methode initialize der Klasse Lok. Damit die Varible @geschwindigkeit weiterhin vorbelegt wird, übernehmen wir alle Werte der initiaze-methode von Lok in Zeile 25 mit dem Command super. Ohne diese Anweisung würden wir die initialize-methode überschreiben. Die Attribute @maxgeschwindigkeit und @typ werden in Zeile 26 und 27 definiert. Natürlich kann eine erbende Klasse auch weitere Methoden beinhalten. Hier ein Beispiel dafür: 32 class Diesellok < Lok 33 34 def initialize 35 super 36 @typ = "Diesel-Lok" 37 @maxgeschwindigkeit = 320 38 @tankinhalt = 0 39 end 40 41 def tanken(wert) 42 @tankinhalt = @tankinhalt + wert 43 end 44 45 def tankinhalt? 46 puts "Tankinhalt: #{@tankinhalt}" 47 end Die Klassen werden nachfolgend ganz einfach initialisiert: 66 stinki = Diesellok.new 67 p stinki 68 stinki.beschleunige(130) 69 stinki.geschwindigkeit? 70 stinki.bremse(20) 71 stinki.geschwindigkeit? 72 stinki.tanken(200) 73 stinki.tankinhalt? Pizza on Rails - 13 -

Mit diesem Beispiel möchte ich den ersten Ausflug in die Objektorientierung abschließen. Es ist leicht ersichtlich, dass gerade die Vererbung ein großes Potential birgt. Wenn man Objekte sinnvoll arrangiert, können Erweiterungen des Objektmodells einfach durch das Hinzufügen von Methoden an einer Stelle an die Kinderobjekte weiter vererbt werden. Im Fall von Ruby gibt es jedoch die Einschränkung, dass eine Klasse immer nur eine Elternklasse haben kann. Eine Klasse kann alle Eigenschaften jeweils einer Elternklasse erben. 2.5 Klassen Objekte werden in der objektorientierten Programmierung durch Klassen definiert. Diese bilden sozusagen den Bauplan für Objekte. Als erstes Beispiel möchte ich einen Taschenrechner programmieren. Dazu definiere ich zunächst die Klasse Calculator. In der UML-Notation, einer beliebten Methode zur Darstellung objektorientierter Systeme, sieht die Klasse zunächst wie folgt aus: Objektname Attribute Methoden Der Code dazu: 1!#/bin/ruby 2 3 class Calculator 4 5 end Pizza on Rails - 14 -

2.5.1 Attribute Attribute sind die Eigenschaften von Objekten. Hier werden also all relevanten Eigenschaften der Objekte definiert. Die Eigenschaften werden in der Methode initialize initiiert. Bei unserem Taschenrechner-Beispiel werden die Eigenschaften wert1, wert2 und ergebnis definiert und in der Methode initialize vordefiniert. In der UML-Notation werden im 1. Block die Objekteigenschaften angegeben: 1!#/bin/ruby 2 3 class Calculator 4 5 def initialize 6 wert1 = 0 7 wert2 = 0 8 ergebnis = 0 9 end 10 11 12 end Pizza on Rails - 15 -

2.5.2 Methoden Neben den Attributen gibt es die Methoden. Sie definieren die Möglichkeiten, auf Attribute zuzugreifen oder sie zu verändern. Auch hier werden lediglich die relevanten Methoden definiert. Ein Objekt wird also in der Regel nie vollständig definiert sein. Der Code dazu: 1!#/bin/ruby 2 3 class Calculator 4 5 def initialize 6 wert1 = 0 7 wert2 = 0 8 ergebnis = 0 9 end 10 11 def addiere(eingabe1, eingabe2) 12 ergebnis = eingabe1 + eingabe2 13 puts "#{eingabe1} + #{eingabe2} = #{ergebnis}" 14 end 15 16 def subtrahiere(eingabe1, eingabe2) 17 ergebnis = eingabe1 - eingabe2 18 puts "#{eingabe1} - #{eingabe2} = #{ergebnis}" 19 end 20 21 def multipliziere(eingabe1, eingabe2) 22 ergebnis = eingabe1 * eingabe2 23 puts "#{eingabe1} * #{eingabe2} = #{ergebnis}" 24 end 25 26 def dividiere(eingabe1, eingabe2) 27 ergebnis = eingabe1 / eingabe2 28 puts "#{eingabe1} / #{eingabe2} = #{ergebnis}" 29 end 30 31 end Pizza on Rails - 16 -

Eine Methode wird innerhalb von def end definiert. Wenn an eine Methode Argumente übergeben werden müssen, so folgen diese in einer Argumentenliste durch Kommata voneinander getrennt (Beisp. Zeile 11). Die im Beispiel angegebenen Klammern sind optional, dienen aber der Übersichtlichkeit. Innerhalb der Methode verwendet man in der Regel lokale Variablen (Beisp. Zeile 17). Mit puts wird in unserem Calculator dass ein Ergebnis ausgegeben. Um innerhalb des Ausgabestrings auf die Variablenwerte zugreifen zu können, werden diese in #{ } gesetzt. Um aus der reinen Klassendefinition ein ablaufendes Programm zu machen, erweitern wir den Code: 33 cal1 = Calculator.new 34 cal1.addiere(10,20) 35 cal1.subtrahiere(12,6) 36 cal1.multipliziere(2,3) 37 cal1.dividiere(6,3) In Zeile 33 instanzieren wir das Calculatorobjekt cal1 mit dem Methodenaufruf new. Damit haben wir aus der Klassendefinition Calculator ein Objekt im Hauptspeicher geschaffen. Die Methoden des Objektes rufen wir einfach mit <objekt>.<methode><argumente> auf. Das Ergebnis gibt uns Recht: 10 + 20 = 30 12-6 = 6 2 * 3 = 6 6 / 3 = 2 [Finished in 0.0s] 2.6 Variablen Attribute werden in Ruby, wie in allen Programmiersprachen, mit Variablen abgebildet. Hier unterscheidet sich Ruby zunächst nicht von anderen Sprachen. Variablen sind in Ruby nicht typisiert. Das ist jedoch ein immenser Unterschied zu anderen Sprachen. Was das konkret bedeutet, zeigt das folgende Beispiel: 1 variable1 = "Hello" 2 p variable1.class 3 variable1 = 123 4 p variable1.class Wir weisen in Zeile 1 der variablen1 einen String und in Zeile3 einen Integer zu. Der Variablenwert wurde nirgendwo definiert, trotzdem weist Ruby derselben Variable den jeweils richtigen Objekttyp zu. String Fixnum [Finished in 0.0s] Praktisch, aber auch tückisch, da der Typ einer Variablen im Programmablauf verändert werden Pizza on Rails - 17 -

kann! 2.6.1 Zahlenwerte Der erste bekannte Variablentyp ist der Typ Integer 1 variable1 = 12345 2 p variable1 3 p variable1.class 4 variable1.to_i 5 p variable1 6 p variable1.class 7 variable1 = variable1 * 1000000000000000000000000000 8 p variable1 9 p variable1.class 10 variable1 = variable1 / 1000000000000000000000000000 11 p variable1 12 p variable1.class 13 variable2 = variable1 / 2 14 p variable2 15 p variable2.class 16 variable2 = variable1 / 2.0 17 p variable2 18 p variable2.class Wir weisen der variablen1 eine Zahl zu, nehmen diese mal 1000000000000000000000000000 und teilen sie darauf wieder durch 1000000000000000000000000000. Wie zu erwarten wird der Variablentyp von Fixnum auf Bignum und wieder zurück angepasst. Beides sind Integer Werte, die sich lediglich durch den intern belegten Speicherplatz unterscheiden. Interessant wird es beim Teilen einer Integer-Zahl durch eine weitere Integer-Zahl (Zeile 13). Das Ergebnis ist eine Integer-Zahl, also nur der genzzahlige Teil des Bruchs! Wenn man korrekten Wert haben möchte, muss man durch eine Float-Zahl ( Zeile 16) teilen. Das Ergebnis ist dann ebenfalls eine Float-Zahl (mit Kommastellen). 12345 Fixnum 12345 Fixnum 12345000000000000000000000000000 Bignum 12345 Fixnum 6172 Fixnum 6172.5 Float [Finished in 0.0s] Pizza on Rails - 18 -

2.6.2 String Wie in allen Programmiersprachen, gibt es auch in Ruby Stringvariablen. Sie werden ganz einfach durch eine Wertzuweisung definiert ( Z.1 / Z.2). Grundsätzlich können dabei doppelte ( ) wie auch einfache (') Anführungszeichen verwendet werden. Der Unterschied liegt darin, dass bei der Verwendung von doppelten Anführungszeichen ein Variable mit #{variable} im String ersetzt wird. Einfache Anführungszeichen lassen eine solche Ersetzung nicht zu. 1 var1 = "Hallo" 2 var2 = 'hallo' 3 ergebnis = 9-5 4 var3 = "Das Ergebnis von 9-5 ist #{ergebnis}" 5 puts var3 6 var4 = 'Das Ergebnis von 9-5 ist #{ergebnis}' 7 puts var4 Das Ergebnis von 9-5 ist 4 Das Ergebnis von 9-5 ist #{ergebnis} [Finished in 0.2s] Oft benutzte Methoden der String-Objekte sind 1. Die Verkettung mit + 2. Die Längenermittlung mit.size 3. Umwandlung in Großbuchstaben mit.upcase 4. Umwandlung in Kleinbuchstaben miz.downcase 5. Umkehrung der Buchstabenreihenfolge mit.reverse 6. Die Umwandlung in eine Integer-Zahl mit.to_i 1 var1 = "Hallo" 2 var2 = 'ich bin die zweite Variable' 3 var3 = "100" 4 puts var1.size 5 puts var1.upcase 6 puts var1.downcase 7 puts var2.reverse 8 puts var3.class 9 var4 = var3.to_i 10 puts var4.class 11 puts var4 5 HALLO hallo elbairav etiewz eid nib hci String Fixnum 100 [Finished in 0.0s] Pizza on Rails - 19 -

2.6.3 Boolean Booleans werden als eigenständige Klassen zugewiesen: 1 var1 = false 2 var2 = true 3 p var1.class 4 p var2 5 p var1.class 6 p var2 FalseClass true FalseClass true [Finished in 0.0s] 2.6.4 Array Ein Array ist eine Sammlung von Objekten. 1 a = [ 1,2,3,4,5,6,7] 2 p a[0] 3 p a.size 4 a<<8 5 p a.size 6 p a 7 a<<"hallo" 8 p a 9 b = [1,2,3,4,5] 10 a<<b 11 p a 1 7 8 [1, 2, 3, 4, 5, 6, 7, 8] [1, 2, 3, 4, 5, 6, 7, 8, "Hallo"] [1, 2, 3, 4, 5, 6, 7, 8, "Hallo", [1, 2, 3, 4, 5]] [Finished in 0.0s] In Zeile 1 definieren wir das Array. Auf ein einzelnes Objekt greift man zu, indem man die Objektnummer (bei 0 beginnend) in Klammern angibt (Zeile 2). Die Größe bekommt man mit der.size Methode angezeigt. Ein weiteres Objekt fügt man mit << an. Interessant ist hierbei, dass es sich dabei um alle möglichen Objekte handeln kann ( Z. 7 und Z.9 ) Pizza on Rails - 20 -

2.6.5 Hash Beim Hash handelt es sich um einen Sonderfall eines Arrays. Hier werden Keys und Values innerhalb einer geschweiften Klammer gespeichert. 1 meine_autos = { 'erstes Auto' => 'Simca', 'zweites Auto' => 'Talbot', 'drittes Auto' => 'Peugeot'} 2 p meine_autos['zweites Auto'] "Talbot" [Finished in 0.0s] 2.6.6 Symbol Ein Symbol ist wie ein Label zu verstehen, dass auf einen Speicherplatz verweist. Eine Symbolvariable wird oft in Hashes verwendet, sie wird initialisiert, indem man dem Variablennamen einen Doppelpunkt voranstellt. 1 meine_autos = { :erstes_auto => 'Simca', :zweites_auto => 'Talbot', :drittes_auto => 'Peugeot'} 2 p meine_autos[:drittes_auto] "Peugeot" [Finished in 0.0s] Pizza on Rails - 21 -

2.6.7 lokale Variablen Grundsätzlich sollten Variablen lokal verwendet werden. Ihre Sichtbarkeit ist dabei auf den jeweiligen Codeblock beschränkt. 1 class Scope 2 3 def initialize 4 var1 = "Hallo" 5 end 6 7 def zeige_an 8 var1 9 end 10 11 end 12 13 sc = Scope.new 14 sc.zeige_an /home/frank/pizzaonrails/variables.rb:8:in `zeige_an': undefined local variable or method `var1' for #<Scope:0x7f40c0d414f0> (NameError) from /home/frank/pizzaonrails/variables.rb:14 [Finished in 0.0s with exit code 1] Die Variable wir außerhalb der Methode initialize nicht mehr gefunden. Gerade zur Vermeidung von Seiteneffekten ein durchaus gewolltes Verhalten! 2.6.8 Instanz-Variablen Durch das Voransetzen eines @ wird die Variable zur Instanz-Variablen. Ihr Wert ist innerhalb der kompletten Instanz sc sichtbar. 1 class Scope 2 3 def initialize 4 @var1 = "Hallo" 5 end 6 7 def zeige_an 8 p @var1 9 end 10 11 end 12 13 sc = Scope.new 14 sc.zeige_an "Hallo" [Finished in 0.0s] Pizza on Rails - 22 -

2.6.9 Class-Variablen Klassen-Variablen sind über die Instanz eines Objekte in allen Objekten einer Klasse sichtbar. Sie werden durch @@ definiert. 1 class Scope 2 3 def initialize 4 @var1 = "Hallo" 5 6 end 7 8 def setze_var0 9 @@var0 = 0 10 end 11 12 def zeige_an 13 p @var1 14 p @@var0 15 end 16 17 def addiere 18 @@var0=@@var0 + 1 19 end 20 21 22 end 23 sc1 = Scope.new 24 sc1.setze_var0 25 sc1.addiere 26 sc1.zeige_an 27 sc2 = Scope.new 28 sc2.zeige_an 29 sc2.addiere Das Ergebnis: Die in Zeile 24 gesetzte und in Zeile 25 um 1 erhöhte Variable @@var0 der Instanz sc1 ist auch der Instanz sc2 der Klasse Scope sichtbar. "Hallo" 1 "Hallo" 1 [Finished in 0.0s] Pizza on Rails - 23 -

2.6.10 Globale-Variablen Durch das Voransetzen von $ wird eine Variable zur Globalen-Variablen. Im gesamten Programm sichtbar. 1 class Scope 2 3 def initialize 4 @var1 = "Hallo" 5 6 end 7 8 def zeige_an 9 p @var1 10 p $var0 11 end 12 13 def addiere 14 $var0=$var0 + 1 15 end 16 17 18 end 19 $var0=0 20 sc1 = Scope.new 21 sc1.zeige_an 22 sc1.addiere 23 sc2 = Scope.new 24 sc2.zeige_an 25 sc2.addiere 26 p $var0 "Hallo" 0 "Hallo" 1 2 [Finished in 0.0s] Pizza on Rails - 24 -

2.7 Schleifen Wie in fast allen Programmiersprachen gibt es natürlich auch in Ruby Schleifen. Die Wichtigsten Schleifen ( Loops ) sind: 2.7.1 While / Until Das bekannteste Beispiel ist die while Schleife: 1 i = 0 2 while i < 5 do 3 puts i 4 i=i+1 5 end 0 1 2 3 4 [Finished in 0.0s] nicht ungewöhnlich ist auch die until-schleife: 1 i = 0 2 until i == 6 do 3 puts i 4 i=i+1 5 end zu Beachten ist der Unterschied zwischen einer Wertzuweisung = und einem Wertevergleich == (Zeile 6). 0 1 2 3 4 5 [Finished in 0.0s] Pizza on Rails - 25 -

2.7.2 each Eine interessante Alternative ist der each-operator. Mit ihm kann über Arrays iteriert werden. 1 i = [1,2,3,4,5,6] 2 i.each do v 3 puts v 4 end In Zeile i wird ein Array definiert. Zeile 2 Speichert jedes einzelne Array-Objekt in der Blockvariablen v ( Das Thema Block folgt später) und printed dessen Wert in Zeile 3 an. Besonders reizvoll ist diese Variante bei der Verwendung von SQL-Abfrageergebnissen, über die man damit einfach iterieren kann. 1 2 3 4 5 6 [Finished in 0.0s] Pizza on Rails - 26 -

2.8 Bedingungen 2.8.1 If.. then else Die if.. then Schleife kann in der einfachen Form so aussehen: 1 i = 10 2 3 if i == 10 then 4 puts "i = #{i}" 5 end i = 10 [Finished in 0.0s] oder alternativ mit einem else-zweig und / oder elseif versehen werden: 1 i = 16 2 3 if i == 10 then 4 puts "i = #{i}" 5 elsif i == 15 6 puts "i == 15" 7 else 8 puts "i <> 10 oder 15" 9 end 10 i <> 10 oder 15 [Finished in 0.0s] Pizza on Rails - 27 -

2.9 Blöcke Blöcke sind eine Besonderheit von Ruby. In dem each Beispiel haben wir den Block schon vorweggenommen. Daher möchte ich ihn hier nochmal diskutieren: 1 i = [1,2,3,4,5,6] 2 i.each do v 3 puts v 4 end In der Zeile 2 wird ein aus einem Iterator gewonnenes Ergebnis über eine sogenannte Blockvariable v an einen Block weitergegeben. Hier können beliebig viele Statements stehen, die den Block dann weiterverarbeiten. Pizza on Rails - 28 -

3 Rails unter der Lupe Ruby on Rails ist ein Framework für die Entwicklung von Webapplikationen. Es wurde von David Heinemeier Hanson entwickelt, um Webapplikationen mit der objektorientierten Sprache Ruby in einer extrem strukturierten Entwicklungsumgebung aufbauen zu können. Um uns dem Framework nähern zu können, schreiben wir zunächst den berühmten Weblog in 15 Minuten. 3.1 Blog in 15 Minuten Um in Rails eine Webapplikation anlegen zu können, bedient man sich zunächst eines Generators. Wir generiern zunächst mit dem Command rails new blog ein Webapplikation mit dem Namen blog. Der rails-generator generiert jetzt eine Reihe von Dateien und Verzeichnissen, die das Ökosystem für die eigentliche Rails-Applikation darstellen. Zunächst wird die Verzeichnisstruktur mit den Systemdateien generiert: $ rails new blog create create README.rdoc create Rakefile create config.ru create.gitignore create Gemfile create app create app/assets/images/rails.png create app/assets/javascripts/application.js create app/assets/stylesheets/application.css create app/controllers/application_controller.rb create app/helpers/application_helper.rb create app/mailers create app/models create app/views/layouts/application.html.erb create app/mailers/.gitkeep create app/models/.gitkeep create config create config/routes.rb create config/application.rb create config/environment.rb create config/environments create config/environments/development.rb create config/environments/production.rb create config/environments/test.rb create config/initializers create config/initializers/backtrace_silencers.rb create config/initializers/inflections.rb create config/initializers/mime_types.rb create config/initializers/secret_token.rb Pizza on Rails - 29 -

create config/initializers/session_store.rb create config/initializers/wrap_parameters.rb create config/locales create config/locales/en.yml create config/boot.rb create config/database.yml create db create db/seeds.rb create doc create doc/readme_for_app create lib create lib/tasks create lib/tasks/.gitkeep create lib/assets create lib/assets/.gitkeep create log create log/.gitkeep create public create public/404.html create public/422.html create public/500.html create public/favicon.ico create public/index.html create public/robots.txt create script create script/rails create test/fixtures create test/fixtures/.gitkeep create test/functional create test/functional/.gitkeep create test/integration create test/integration/.gitkeep create test/unit create test/unit/.gitkeep create test/performance/browsing_test.rb create test/test_helper.rb create tmp/cache create tmp/cache/assets create vendor/assets/javascripts create vendor/assets/javascripts/.gitkeep create vendor/assets/stylesheets create vendor/assets/stylesheets/.gitkeep create vendor/plugins create vendor/plugins/.gitkeep run bundle install Dann werden mit einem sogenannten Bundler die notwendigen Systemblbliotheken des Frameworks dazukopiert: Fetching gem metadata from https://rubygems.org/... Fetching gem metadata from https://rubygems.org/.. Installing rake (10.0.3) Installing i18n (0.6.1) Installing multi_json (1.5.0) Using activesupport (3.2.6). Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed. Pizza on Rails - 30 -

Jetzt wechseln wir in das Verzeichnis blog und starten mit rails server den Webserver: frank@pornb8298:/media/sda9/frank/tutorial-scr$ cd blog frank@pornb8298:/media/sda9/frank/tutorial-scr/blog$ rails server => Booting WEBrick => Rails 3.2.6 application starting in development on http://0.0.0.0:3000 => Call with -d to detach => Ctrl-C to shutdown server SECURITY WARNING: No secret option provided to Rack::Session::Cookie. This poses a security threat. It is strongly recommended that you provide a secret to prevent exploits that may be possible from crafted cookies. This will not be supported in future versions of Rack, and future versions will even invalidate your existing user cookies. Called from: /home/frank/.rvm/gems/ruby-1.8.7-p358/gems/actionpack- 3.2.6/lib/action_dispatch/middleware/session/abstract_store.rb:28:in `initialize'. [2013-01-09 16:57:43] INFO WEBrick 1.3.1 [2013-01-09 16:57:43] INFO ruby 1.8.7 (2012-02-08) [x86_64-linux] [2013-01-09 16:57:48] INFO WEBrick::HTTPServer#start: pid=5875 port=3000 Das Ergebnis können wir direkt unter der Adresse localhost:3000 im Browser sehen Pizza on Rails - 31 -

Das Grundgerüst steht. Nun müssen wir den Weblog entwickeln. Er soll ganz einfach aus einer Überschrift und einem Textbereich bestehen. Dazu benutzen wir erneut einen Generator namens scaffold: rails generate scaffold weblog titel:string memo:text SECURITY WARNING: No secret option provided to Rack::Session::Cookie. This poses a security threat. It is strongly recommended that you provide a secret to prevent exploits that may be possible from crafted cookies. This will not be supported in future versions of Rack, and future versions will even invalidate your existing user cookies. Called from: /home/frank/.rvm/gems/ruby-1.8.7-p358/gems/actionpack- 3.2.6/lib/action_dispatch/middleware/session/abstract_store.rb:28:in `initialize'. invoke active_record create db/migrate/20130109160710_create_weblogs.rb create app/models/weblog.rb invoke test_unit create test/unit/weblog_test.rb create test/fixtures/weblogs.yml invoke resource_route route resources :weblogs invoke scaffold_controller create app/controllers/weblogs_controller.rb invoke erb create app/views/weblogs create app/views/weblogs/index.html.erb create app/views/weblogs/edit.html.erb create app/views/weblogs/show.html.erb create app/views/weblogs/new.html.erb create app/views/weblogs/_form.html.erb invoke test_unit create test/functional/weblogs_controller_test.rb invoke helper create app/helpers/weblogs_helper.rb invoke test_unit create test/unit/helpers/weblogs_helper_test.rb invoke assets invoke coffee create app/assets/javascripts/weblogs.js.coffee invoke scss create app/assets/stylesheets/weblogs.css.scss invoke scss create app/assets/stylesheets/scaffolds.css.scss Nun müssen wir noch schnell eine Datenbank anlegen: rake db:migrate == CreateWeblogs: migrating ================================================== -- create_table(:weblogs) -> 0.0018s == CreateWeblogs: migrated (0.0019s) ========================================= Den server erneut starten: $ rails server und fertig ist unsere Applikation Pizza on Rails - 32 -

Nachdem wir die Adresse localhost:3000/weblogs aufgerufen haben, sehen wir: zunächst eine leere Liste. Wenn wir auf new weblog klickt erscheint das Eingabescreen: Pizza on Rails - 33 -

Pizza on Rails - 34 -

Mit create Weblog gelangt man in die sogenannte show-view, in der der erzeugte Datensatz angezeigt wird: Pizza on Rails - 35 -

Und über back in die List-View: Pizza on Rails - 36 -

3.2 Aufbau einer Rails Application 3.2.1 Die Rails Komponenten Als nächste beschäftigen wir uns mit dem Aufbau einer Rails-Applikation. Grundsätzlich besteht eine Rails-Application aus Models, Views und Controller. Den Aufbau möchte ich in einer kleinen Graphik darstellen: Pizza on Rails - 37 -

Als Beispiel betrachten wir die Abfrage der Auflistung der Weblog-Anträge unserer gerade geschriebenen Applikation. Über unseren Webbrowser rufen wir die Adresse http://localhost:3000/weblogs auf (1). Der Web-Server nimmt die Anfrage entgegen und ermittelt aus der URL der Anfrage und seiner Konfiguration, dass die Anfrage an die Rails-Applikation weblog weitergegeben werden muss. Innerhalb der Applikation ruft er den Router auf (2). Der Router erkennt aufgrund der URL ( /weblogs), dass die Methode (action) index des weblogs _controllers aufgerufen werden muss (3). Der Controller wiederum gibt den find :all Befehl an das Model weiter (4). Im Model ist zum einen die Business-Logik der logischen Objekte definiert, zum Anderen wird über eine Object Reational Mapper (Active-Record) die Verbindung zur Datenbank hergestellt (5). Die Datenbank führt den select * from weblogs Befehl aus und gibt das Ergebnis über das Model in den Controller zurück. Der Controller erkennt an der URL dass er normales HTML an den Anwender zurückgeben soll und gibt das aus der Datenbank kommende Objekt zur Aufbereitung in HTML an die View weiter (6). In der View wird die HTML der Ausgabeseite definiert und an den Web-Server weitergeleitet (7). Der Webserver wiederum gibt die so generierte Webseite an den Browser des Rechners zurück (8). Pizza on Rails - 38 -

3.2.2 Skeletton Betrachten wir nun den physischen Aufbau der Rails-Applikation: blog app... config... config.ru db... doc... Gemfile Gemfile.lock lib... log... public... Rakefile README.rdoc script... test... tmp... vendor assets... plugins Pizza on Rails - 39 -

Die Applikation besteht im groben aus einem app-verzeichnis für die Applikation, sowie diversen Konfigurationsdateien. Als erstes möchte ich einen Blick auf das config-verzeichnis werfen. In diesem Verzeichnis befinden sich die anwendungsspezifischen Konfigurationsdateien: config application.rb boot.rb database.yml environment.rb environments development.rb production.rb test.rb initializers backtrace_silencers.rb inflections.rb mime_types.rb secret_token.rb session_store.rb wrap_parameters.rb locales en.yml routes.rb Wie man sieht besteht die Applikation aus drei Grundkonfigurationen test, development und production. Der Grund dafür ist, dass man hier drei unterschiedliche Datenquellen definieren kann. Eine Test-Umgebung besteht als Datenquelle immer nur temporär. Vor dem Test werden die Daten geladen, nach Testabschluss wieder gelöscht. Die Development-Umgebung ist die übliche Entwicklungsungebung mit einem Datenextrakt, der die typischen Scenarien abdeckt. Die Produktionsumgebung ist die Umgebung in die die Anwendung deployed wird, also die produktive Datenbank. Pizza on Rails - 40 -

Betrachten wir zunächst die Datei database.yml 1 # SQLite version 3.x 2 # gem install sqlite3 3 # 4 # Ensure the SQLite 3 gem is defined in your Gemfile 5 # gem 'sqlite3' 6 development: 7 adapter: sqlite3 8 database: db/development.sqlite3 9 pool: 5 10 timeout: 5000 11 12 # Warning: The database defined as "test" will be erased and 13 # re-generated from your development database when you run "rake". 14 # Do not set this db to the same as development or production. 15 test: 16 adapter: sqlite3 17 database: db/test.sqlite3 18 pool: 5 19 timeout: 5000 20 21 production: 22 adapter: sqlite3 23 database: db/production.sqlite3 24 pool: 5 25 timeout: 5000 In den Zeilen 6-10 wird die development-datenbank definiert. Wenn man nichts anderes einträgt, wird hier eine sqlite3-datenbank verwendet. Im produktivem Umfeld steht hier oftmals eine MySql- Datenbank. Zeile 15 19 definiert die Testdatenbank und Zeile 21 25 die Produktionsdatenbank. Von Interesse ist hier auch die routes.rb-datei. In ihr definiert man, welche Methode (bie Rails auch action genannt) im jeweiligen Controller von einer URL angesprochen werden soll. Da Rails als oberste Maxime Convention over Configuration hat, genügt ein einziger Eintrag: 1 Blog::Application.routes.draw do 2 resources :weblogs 3 4 # The priority is based upon order of creation: 5 # first created -> highest priority. 6 7 # Sample of regular route: 8 # match 'products/:id' => 'catalog#view' 9 # Keep in mind you can assign values other than :controller and :action 10 Zeile 2 definiert eine Ressource weblogs mit allen standardmäßig zu ihr gehörenden Routen. Genaueres sehen wir im Kapitel Controller. Zunächst können wir es mit diesem kurzen Blick in die Konfigurationsdateien belassen. Pizza on Rails - 41 -

Kommen wir zum eigentlichen Applikations-Verzeichnis app. app assets images rails.png javascripts application.js weblogs.js.coffee stylesheets application.css scaffolds.css.scss weblogs.css.scss controllers application_controller.rb weblogs_controller.rb helpers application_helper.rb weblogs_helper.rb mailers models weblog.rb views layouts application.html.erb weblogs edit.html.erb _form.html.erb index.html.erb new.html.erb show.html.erb Hier finden sich neben den assets, einem Verzeichnis mit applikationsspezifischen Javascript- Dateien, Bildern und CSS-Stylesheets, sowie einem helpers und mailers-verzeichnis die für uns zunächst wichtigen Verzeichnisse controllers, models und views. Pizza on Rails - 42 -

3.2.3 Controller Im controllers-verzeichnis befinden sich alle Controller-Dateien der Applikation. Jedes Objekt, das wir in einer Applikation definieren hat dabei eine eigene Controller-Datei. Im Folgenden möchte ich einen Blick auf die Controller-Datei des Weblogs-Objekt werfen. 1 class WeblogsController < ApplicationController 2 # GET /weblogs 3 # GET /weblogs.json 4 def index 5 @weblogs = Weblog.all 6 7 respond_to do format 8 format.html # index.html.erb 9 format.json { render :json => @weblogs } 10 end 11 end 12 13 # GET /weblogs/1 14 # GET /weblogs/1.json 15 def show 16 @weblog = Weblog.find(params[:id]) 17 18 respond_to do format 19 format.html # show.html.erb 20 format.json { render :json => @weblog } 21 end 22 end 23 24 # GET /weblogs/new 25 # GET /weblogs/new.json 26 def new 27 @weblog = Weblog.new 28 29 respond_to do format 30 format.html # new.html.erb 31 format.json { render :json => @weblog } 32 end 33 end 34 35 # GET /weblogs/1/edit 36 def edit 37 @weblog = Weblog.find(params[:id]) 38 end 39 40 # POST /weblogs 41 # POST /weblogs.json 42 def create 43 @weblog = Weblog.new(params[:weblog]) 44 45 respond_to do format 46 if @weblog.save 47 format.html { redirect_to @weblog, :notice => 'Weblog was successfully created.' } 48 format.json { render :json => @weblog, :status => :created, :location => @weblog } 49 else Pizza on Rails - 43 -

50 format.html { render :action => "new" } 51 format.json { render :json => @weblog.errors, :status => :unprocessable_entity } 52 end 53 end 54 end 55 56 # PUT /weblogs/1 57 # PUT /weblogs/1.json 58 def update 59 @weblog = Weblog.find(params[:id]) 60 61 respond_to do format 62 if @weblog.update_attributes(params[:weblog]) 63 format.html { redirect_to @weblog, :notice => 'Weblog was successfully updated.' } 64 format.json { head :no_content } 65 else 66 format.html { render :action => "edit" } 67 format.json { render :json => @weblog.errors, :status => :unprocessable_entity } 68 end 69 end 70 end 71 72 # DELETE /weblogs/1 73 # DELETE /weblogs/1.json 74 def destroy 75 @weblog = Weblog.find(params[:id]) 76 @weblog.destroy 77 78 respond_to do format 79 format.html { redirect_to weblogs_url } 80 format.json { head :no_content } 81 end 82 end 83 end Wir untersuchen nun einzelne Statements. In Zeile 1 wird die Klasse WeblogsController als Childklasse der Klasse ApplikationController definiert. 1 class WeblogsController < ApplicationController Sehen wir uns nun die ebenfalls im Verzeichnis controllers stehende Datei application_controller.rb an: 1 class ApplicationController < ActionController::Base 2 protect_from_forgery 3 end Hier wird in der Zeile 1 der ApplicationController als Childklasse der Klasse ActionController definert, Wenn man weiß dass der ActionController Teil des Rails-Frameworks ist, dann ist klar wie das Framework mit den Klassen verbunden wird die Klassen erben jeweils von einer Frameworkklasse alle relevanten Methoden. Pizza on Rails - 44 -

Die erste wichtige Methode der Weblogs-Klasse ist die Methode index. 4 def index 5 @weblogs = Weblog.all 6 7 respond_to do format 8 format.html # index.html.erb 9 format.json { render :json => @weblogs } 10 end 11 end Neben dem üblichen def...end in Zeile 4 und 11 wird in Zeile 5 der Instanzvariable @weblogs der wert von Weblog.all zugewiesen. Hinter Weblog.all steht der Aufruf des Models Weblog ( wird noch nachfolgend erklärt) mit der Kurzform des find_all Befehls. Dieser Befehl ist wiederum Teil des ActiveRecord Frameworks von Rails und kapselt den folgenden SQL-Befehl: SELECT "weblogs".* FROM "weblogs" Neben diesem find_all gibt es noch eine Vielzahl von Findern, die alle möglichen Select-Befehle einer Datenbank kapseln. Warum macht man das? Zum einen umgeht man damit Eigenarten der Datenbanken. Wenn ein Framework universell sein will, muss es auch mit allen möglichen Datenbanken kommunizieren können. Das sind zum einen natürlich SQL-Datenbanken, zum anderen die neueren objektorientierten non-sql-datenbanken wir CouchDB... Zum anderen verbirgt sich hinter ActiveRecord ein sogenannter Object Relaational Mapper. Objektorientiert betrachtet ist ja jede Zeile der Weblogs-Tabelle ein Weblogs-Objekt, dass man dann mit objektspezifischen Mathoden ansprechen kann. Diese Objekte werden als Models definiert. Das Ergebnis wird wie gesagt in die Variable @weblogs geschriebenen. In Zeile 7-9 wird je nach der mitgegebenen URL die Ausgabe im Format html an die entsprechende View weitergegeben oder als.json File für Webservices ausgegeben. Die Methode index wird mit der URL http://localhost:3000/weblogs aufgerufen, Pizza on Rails - 45 -

In Zeile 15 22 wird die Metode show definiert, Sie wird über die URL http://localhost:3000/weblogs/1 aufgerufen, wobei 1 den ersten Datensatz spezifiziert. Man gelangt zu der URL, indem man in der Index View beispielsweise im 1, Datensatz auf den show-link drückt. 15 def show 16 @weblog = Weblog.find(params[:id]) 17 18 respond_to do format 19 format.html # show.html.erb 20 format.json { render :json => @weblog } 21 end 22 end In Zeile 15 wird wieder Finder auf das Weblog-Model aufgerufen, diesmal wir ihm der in der URL mitgegebene Parameter und die zu durchsuchende Spalte id mitgegeben. Wie bei relationalen Datenbanken üblich besitzt jede Zeile der Tabelle Weblogs eine id-spate mit einer eindeutigen Integer-Zahl. Der aus dem Finder resultierende SQL-Befehl lautet: SELECT "weblogs".* FROM "weblogs" WHERE "weblogs"."id" =? LIMIT 1 [["id", "1"]] Das Ergebnis wird wieder in der Variablen @weblogs gespeichert und in den Zeilen 18 21 an je nach gewünschtem Tüp gerendert. Wenn in der URL nichts angegebenen ist, wird html angenommen. Gibt man aber beispielsweise die folgende URL an: http://localhost:3000/weblogs/1.sonj resultiert daraus der folgende, von anderen Applikation weiterverarbeitbare Datenstrom im JSON- Format: {"updated_at":"2013-01-09t16:15:22z","memo":"rails ist gar nicht schwer!","created_at":"2013-01-09t16:15:22z","titel":"mein erster Blogeintrag","id":1} Ein neuer Eintrag wird über die Methode new initiiert: 26 def new 27 @weblog = Weblog.new 28 29 respond_to do format 30 format.html # new.html.erb 31 format.json { render :json => @weblog } 32 end 33 end Hier wird Einfach mit Weblog.new ein neuer Datensatz angelegt und über die new.html.erb-view mit Daten gefüllt (Weiteres dazu in der View-Beschreibung). Damit wird aber lediglich die new-view zur Eingabe der Daten aufgerufen. Das Schreiben des neuen Datensatzes in die Datenbank geschieht später in der create-methode. Pizza on Rails - 46 -

42 def create 43 @weblog = Weblog.new(params[:weblog]) 44 45 respond_to do format 46 if @weblog.save 47 format.html { redirect_to @weblog, :notice => 'Weblog was successfully created.' } 48 format.json { render :json => @weblog, :status => :created, :location => @weblog } 49 else 50 format.html { render :action => "new" } 51 format.json { render :json => @weblog.errors, :status => :unprocessable_entity } 52 end 53 end 54 end Die Variable @weblog wird nun mit dem aus der new-view zurückgegebenen :weblog-objekt bestückt. Entsprechend des Ergebnisses des im Framework automatisch durchgeführten save- Befehls auf die Datenbank wird im Erfolgsfall (Zeile 47, 48) entweder als html-message 'Weblog was successfully created.' oder in JSON der Status created zurückgeben. Die URL ist: http://localhost:3000/weblogs/new der von ActiveRecord erzeugte SQL-BEfehl: INSERT INTO "weblogs" ("created_at", "memo", "titel", "updated_at") VALUES (?,?,?,?) [["created_at", Mon, 14 Jan 2013 14:23:52 UTC +00:00], ["memo", "mein zweiter Blogeintrag"], ["titel", "zweiter Blog"], ["updated_at", Mon, 14 Jan 2013 14:23:52 UTC +00:00]] Um einen bestehenden Eintrag zu editieren, wird analog der Neuanlage zunächst die edit-methode und dann aus der edit-view die update-methode aufgerufen. Sehen wir uns zunächst die edit-methode an: 36 def edit 37 @weblog = Weblog.find(params[:id]) 38 end Ähnlich der show-methode wird ein Eintrag anhand seiner :id gesucht und in der Variablen @weblog gespeichert. Der Inhalt von @weblog wird an die korrespondierende View weitergegeben und dann in der update-methode gehandelt: Pizza on Rails - 47 -

58 def update 59 @weblog = Weblog.find(params[:id]) 60 61 respond_to do format 62 if @weblog.update_attributes(params[:weblog]) 63 format.html { redirect_to @weblog, :notice => 'Weblog was successfully updated.' } 64 format.json { head :no_content } 65 else 66 format.html { render :action => "edit" } 67 format.json { render :json => @weblog.errors, :status => :unprocessable_entity } 68 end 69 end 70 end Auch hier sind die Mechanismen bekannt. Man sucht in Zeile 59 wieder das Weblog über die id, um ihn dann mit den im :weblog übergebenen Objekt zu überschreiben (Zeile 62). Gelingt dies so wird 'Weblog was successfully updated.' zurückgeben. Funktioniert das Schreiben des Datensatzes nicht, wird automatisch wieder in die edit-view zurückgeben. Aufgerufen wird edit mit: http://localhost:3000/weblogs/1/edit Die resultierende SQL lautet: SELECT "weblogs".* FROM "weblogs" WHERE "weblogs"."id" =? LIMIT 1 [["id", "1"]] Nach Abschluß der Eingaben folgt: UPDATE "weblogs" SET "memo" = 'Rails ist gar nicht so schwer!', "updated_at" = '2013-01-14 15:22:28.198010' WHERE "weblogs"."id" = 1 Pizza on Rails - 48 -

Bleibt letztlich noch die delete-action. Das Framework gibt zunächst nach anklicken des Links eine Sicherheitsabfrage aus, um dann zu der destroy-action weiterzuleiten. 74 def destroy 75 @weblog = Weblog.find(params[:id]) 76 @weblog.destroy 77 78 respond_to do format 79 format.html { redirect_to weblogs_url } 80 format.json { head :no_content } 81 end 82 end In Zeile 75 wird die @weblog-variable mit dem über die :id gefundenen Objekt gefüllt. In Zeile 76 wird dann der eigentliche derstroy durchgeführt. Bleibt letztlich noch die delete-action. DELETE FROM "weblogs" WHERE "weblogs"."id" =? [["id", 2]] Die genannten Aktionen nennt man entsprechend den Methoden Create, Read, Update, Delete auch CRUD-Aktionen. Die Notation der URL entspricht dem sogenannten REST (Representational Stateless Transfer) Standard. Da die Rails Applikationen JSON-Objekte zurückgeben können, kann man mit ihnen einfach über Webservices mit anderen Web-Applikationen kommunizieren. Pizza on Rails - 49 -

3.2.4 Model Das Model bildet zum einen die Schnittstelle zur Datenbank, denn als Objekt gesehen wird es auf der Datenbank gespeichert (persistiert), zum anderen beinhaltet es die gesamte Business-Logik der Applikation, In unserem Beispiel ist davon wenig zu sehen, da wir außer dem Weblog-Model kein weiteres Model in unserer Anwendung vorgesehen haben. Daher besteht die Datel weblog.rb im models-verzeichnis nur aus wenigen Zeilen: 1 class Weblog < ActiveRecord::Base 2 attr_accessible :memo, :titel 3 end In Zeile 1 verbindet sich das Model mit dem ActiveRecord aus dem Rails Framework. Hierüber erbt es alle datenbankspezifischen Methoden, wie z.b. die Finder, update und destroy In Zeile 2 werden die Attribute :memo und :titel von aussen zugreifbar gemacht. Obwohl das Model hier unscheinbar daherkommt, beinhaltet es die Fähigkeit, Datenbanksätze als Objekte umgewandelt zu bekommen. Per Definition mappt das Model Weblog die Datrenbanktabelle Weblogs. Pizza on Rails - 50 -

3.2.5 View Die Views sind für die Generierung der HTML an den Browser zuständig. Da es sich dabei um html-files mit sogenanntem embedded Ruby handelt werden sie als.html.erb abgekürzt. HTML-Grundkenntnisse werden hier zwar vorausgesetzt, werden jedoch im Folgenden auch schnell erworben. Index-View Sehen wir uns zunächst die Index-View an: 1 <h1>listing weblogs</h1> 2 3 <table> 4 <tr> 5 <th>titel</th> 6 <th>memo</th> 7 <th></th> 8 <th></th> 9 <th></th> 10 </ tr> 11 12 <% @weblogs.each do weblog %> 13 <tr> 14 <td><%= weblog.titel %></td> 15 <td><%= weblog.memo %></td> 16 <td><%= link_to 'Show', weblog %></td> 17 <td><%= link_to 'Edit', edit_weblog_path(weblog) %></td> 18 <td><%= link_to 'Destroy', weblog, :method => :delete, :data => { :confirm => 'Are you sure?' } %></ td> 19 </ tr> 20 <% end %> 21 </ table> 22 23 <br /> 24 25 <%= link_to 'New Weblog', new_weblog_path %> In Zeile 1 wird mit <h1>...</h1> die Übetrschrift definiert. Darauf folgt von Zeile 3 bis Zeile 21 mit <table>...></table> die Definition einer Tabelle. Die Tabellenköpfe werden in der ersten Tabellenreihe <tr>..</tr> in den Zeilen 5 und 6 in den Tags <th>...</th> definiert. Die eigentliche Rails Magie entsteht in den Zeilen 12 bis 20. Wir erinnern uns: Die Index View wurde aufgerufen, nachdem der Controller in der Methode index über einen Finder alle Weblog- Einträge in die Variable @weblogs geschrieben hat. Um einen Ruby-Befehl in html.erb einzufügen, muss man ihn in <% %> setzen. Wir setzen zunächst einen each.iterator über das @weblogs-objekt aus dem Controller und speichern jedes gefundene Objekt in der Blockvariablen weblog ab ( Zeile 12). In dem in Zeile 20 abgeschlossenen Bock werden jetzt in einer neuen html-zeile <tr>...</tr> (Zeile 13 bis 19) mit dem Tag <td>...</td> jeweils als Spalteneinträge der Titel und die Memo des weblog-objekts ausgegeben. Da hier jeweils ein Ergebnis aus Ruby ausgegeben wird werden die Statements mit <%=. %> gekapselt. Pizza on Rails - 51 -

In Zeile 16 wird ein Link zur Show-Methode des Controllers mit der Übergabe des aktuellen weblog-objekts definiert. Die Zeilen 17 und 18 definieren die Edit und Destroy-Links zum Controller. Dieser Block wird bis zum Ende aller in @weblogs gespeicherten Objekte durchgeführt. Schlussendlich wird in Zeile 25 noch der Link zur new-action für den Controller definiert, Edit-View Der nächste Blick gilt der Edit-View. Sie ist erstaunlich kurz: 1 <h1>editing weblog</h1> 2 3 <%= render 'form' %> 4 5 <%= link_to 'Show', @weblog %> 6 <%= link_to 'Back', weblogs_path %> In Zeile 1 steht die Überschrift, die Zeile5 und 6 setzen die Links zur Show Action des Controllers und Zeile 6 führt zurück zur aufrufrnden View. Hier steckt die Magie in Zeile 3. Mit dem Befehl render 'form' wird ein sogenanntes Partial mit dem Namen _form.html.erb aufgerufen. 1 <%= form_for(@weblog) do f %> 2 <% if @weblog.errors.any? %> 3 <div id="error_explanation"> 4 <h2><%= pluralize(@weblog.errors.count, "error") %> prohibited this weblog from being saved:</ h2> 5 6 <ul> 7 <% @weblog.errors.full_messages.each do msg %> 8 <li><%= msg %></li> 9 <% end %> 10 </ ul> 11 </ div> 12 <% end %> 13 14 <div class="field"> 15 <%= f.label :titel %><br /> 16 <%= f.text_field :titel %> 17 </ div> 18 <div class="field"> 19 <%= f.label :memo %><br /> 20 <%= f.text_area :memo %> 21 </ div> 22 <div class="actions"> 23 <%= f.submit %> 24 </ div> 25 <% end %> In der Zeile 1 wird ein Form-Objekt definier und der Blockvariablen f zugewiesen. Auf dieses Objekt werden dann alle HTML-Methoden angewendet. Sollte es im Verlauf der Action zu Fehlern kommen, werden diese in der <div id= error_explanation>...</div> ausgegeben. Die <div>s vin Zeile 14 bis 20 geben die Felder Titel mit einem Label aus. In den Zeilen 22 24 wird die <div class= actions > mit dem Submit- Button definiert. Die class= Bezeichnungen verweisen auf Klassen in den css-files. Dort werden dann die Textauszeichnungen wie Farbe, Font, Größe etc beschrieben. Mit der Partial- Definition haben wir ein einfaches Grundgerüst für die folgende View geschrieben. Pizza on Rails - 52 -