Nils Haldenwang, B.Sc.
Gastvortrag Datenbanksysteme:
Ruby on Rails
Institut für InformatikAG Medieninformatik1
Monday, June 17, 13
• plattformunabhängige General Purpose Programmiersprache
• Veröffentlichung 1995 in Japan
• außerhalb Japans bekannt geworden um 2000
• Objektorientierung
• dynamische Typisierung (Duck Typing)
• Garbagecollection
• aktuelle Version: 2.0.0, veröffentlicht im Mai 2013
Ruby
2
Monday, June 17, 13
Ruby
I hope to see Ruby help every programmer in the world to be productive, and to enjoy programming, and to be happy. That is the primary purpose of the Ruby language.
- Yukihiro Matsumoto
3
Monday, June 17, 13
RubyEinführung in die Syntax
4
Monday, June 17, 13
Quellen / Literaturempfehlungen
Ruby
2.0.0 Core API: http://www.ruby-doc.org/core-2.0.0/
5
Ruby Dokumentation: http://www.ruby-doc.org/
Monday, June 17, 13
Quellen / Literaturempfehlungen
Ruby6
Dave ThomasChad Fowler,Andy Hunt,Programming Ruby 1.9Pragmatic Bookshelf, 2009
Monday, June 17, 13
Quellen / Literaturempfehlungen
Ruby7
Paolo PerrottaMetaprogramming RubyPragmatic Bookshelf, 2010
Monday, June 17, 13
Hello World
puts "Hello World!"
Ausgabe Stringliteral
hello_world.rb
$ ruby hello_world.rbHello World!
Ruby8
Monday, June 17, 13
local_variable = "Lokale Variable"@instance_variable = "Instanzvariable"@@class_variable = "Klassenvariable"$global_variable = "Globale Variable"SOME_CONSTANT = "Konstante"SomeClass # Klassenkonstante
Variablen
9
Monday, June 17, 13
Basisdatentypen
Ruby
natural_number = 42natural_number.class # => Fixnum, konstante Zahl
float_number = 42.0float_number.class # => Float, Fließkommazahl
string = "Hello World!"string.class # => String
symbol = :hello_worldsymbol.class # => Symbol, konstanter String
10
Monday, June 17, 13
Collections: Array
a = []a = Array.new
a = [42, "foo", nil]
puts a[0] # Ausgabe: 42
puts a.size # Ausgabe: 3
a[0] = 24
Ruby11
Monday, June 17, 13
Collections: Hashh = Hash.newh = {}
h = { :a => "b", :c => 42, "e" => "f", 42 => "The answer,..."} # 1.8 && 1.9
puts h[:a] # Ausgabe: bputs h[42] # Ausgabe: The answer,..
h[:c] = 73
h = { a: "b", c: 42} # Nur 1.9
Ruby
Hashrocketwenn keine Symbole
Doppelpunktbei Symbolen
12
Monday, June 17, 13
DemoRuby13
Monday, June 17, 13
Methodendef say_goodnight(name) result = "Good night, " + name return resultend
puts( say_goodnight("John-Boy") )# => Good night, John-Boy
puts say_goodnight "John-Boy"puts say_goodnight("John-Boy")
def say_goodnight(name) result = "Good night, #{name}" return resultend
def say_goodnight(name) "Good night, #{name}"end
14
Klammern optional
Rückgabewertist der Wert des letzten Ausdruckes.
EmpfohleneSchreibweise
Monday, June 17, 13
Bedingte Anweisungen
if x == 5 puts "x is 5"end
puts "x is 5" if x == 5
if x == 5 puts "x is 5"elsif x == 3 puts "x is 3"else puts "x is unknown"end
Obacht!Ruby15
Monday, June 17, 13
Bedingte Anweisungenif !( x == 5 ) puts "x isn't 5"end
puts "x isn't 5" if !( x == 5 )
unless x == 5 puts "x is not 5"end
puts "x is not 5" unless x == 5
Ruby16
Monday, June 17, 13
Schleifen
i = 42while i > 0 puts i i -= 1end
i = 42until i == 0 puts i i -= 1end
a = [1, 2, 3, 4, 5]
for element in a puts elementend
Ruby17
Monday, June 17, 13
Collatz
Ruby
public class Collatz { public static int value(int x){
int z = 0;
while (x != 1) {
if (x % 2 == 0) x = x / 2; else x = 3*x+1;
z = z+1; }
return z; }}
Ruby18
Monday, June 17, 13
public class Collatz { public static int value(int x){
int z = 0;
while (x != 1) {
if (x % 2 == 0) x = x / 2; else x = 3*x+1;
z = z+1; }
return z; }}
def collatz(x) iterations = 0
while (x != 1)
if (x % 2 == 0) x = x / 2 else x = 3*x + 1 end
iterations = iterations + 1 end
return iterationsend
Collatz
Ruby19
Monday, June 17, 13
def collatz(x) iterations = 0
until x == 1
if x.even? x /= 2 else x = 3*x + 1 end
iterations += 1 end
iterationsend
Collatz
def collatz(x) iterations = 0
while (x != 1)
if (x % 2 == 0) x = x / 2 else x = 3*x + 1 end
iterations = iterations + 1 end
return iterationsend
Ruby20
Monday, June 17, 13
Blöcke
{ puts "Hello, Block!" }
do puts "Hello, Block!" puts "Multiple lines."end
Ruby21
Monday, June 17, 13
Blöcke übergeben
greet_block { puts "Hello, Block!" }
greet_block do puts "Hello, Block!"end
Ruby22
Monday, June 17, 13
Blöcke aufrufen
def call_block puts "Calling block:" yield yield puts "Block has been called."end
call_block { puts "Hello" }
# Ausgabe:# Calling block:# Hello# Hello# Block has been called.
Ruby23
Monday, June 17, 13
Blöcke mit Parametern
def call_block yield("foo")end
call_block { |param| puts "Param: #{param}" }
call_block do |param| puts "Param: #{param}"end
# Ausgabe:# Param: foo
Ruby24
Monday, June 17, 13
Variablen und Blöcke
def call_block yieldend
var = 42
call_block { var = 73 }
puts var
# Ausgabe: 73
Ruby25
Monday, June 17, 13
Optionale Blöcke
def greet(name)
if block_given? yield name else puts "Hello, #{name}!" end
end
greet "Joe" # Ausgabe: Hello, Joe!
greet( "Joe" ) { |name| puts "Nice to meet you, #{name}!" }# Ausgabe: Nice to meet you, Joe!
Ruby26
Monday, June 17, 13
Iteratoren mit Blöcken
a = ["iterators", "rock"]
a.each { |e| puts e }
# Ausgabe:# iterators# rock
h = { a: 42, b: 73 }
h.each { |k, v| puts "key: #{k}, value: #{v}" }
# Ausgabe:# key: a, value: 42# key: b, value: 73
Ruby27
Monday, June 17, 13
Schleifen mit Blöcken3.times { |i| puts i }# Ausgabe:# 0# 1# 2
1.upto(3) { |i| puts i }# Ausgabe:# 1# 2# 3
3.downto(1) { |i| puts i }# Ausgabe:# 3# 2# 1
Ruby28
Monday, June 17, 13
DemoRuby29
Monday, June 17, 13
RubyInstallation
30
Monday, June 17, 13
Ruby installieren
Ruby Version Managerhttp://beginrescueend.com/
Ruby Installerhttp://rubyinstaller.org/
Ruby31
Monday, June 17, 13
Ruby
Ruby installieren mit RVM$ rvm install 2.0.0
$ rvm use 2.0.0$ irb2.0.0-p0 >
32
Monday, June 17, 13
Ruby on Rails
Monday, June 17, 13
Ruby on Rails
• In Ruby geschriebenes Webapplication Framework
• Forciert Resource-Oriented Architecture
• Erstes Framework seiner Art
• Open Source
• 2005 Veröffentlichung Version 1.0
• Aktuelle Version: 3.2.13, erschienen im März 2013
34 Ruby on Rails
Monday, June 17, 13
Ruby on Rails
Rails is about allowing beautiful code to solve the problems most people have most of the time in web-application development. It’s about taking the pain away and making you happy.
This might all sound mighty fluffy, but only until you recognize that the single-most important factor in programmer productivity is motivation. And, happy programmers are certainly motivated programmers. Thus, if you optimize for happiness, you’re optimizing for motivation, which ultimately leads to an optimization for productivity.
- David Heinemeier Hansson35 Ruby on Rails
Monday, June 17, 13
Quellen/Literatur
Sam Ruby, Dave Thomas,David Heinmeier Hansson,
Agile Web Development with Rails,Fourth Edition
Pragmatic Bookshelf, 2011
< 4 ist veraltet: Rails 2
Ruby on Rails
Monday, June 17, 13
Quellen/Literatur
Ruby on Rails
Obie Fernandez,The Rails 3 Way,
Addison-Wesley Professional,2nd Edition, 2010
Erste Edition ist veraltet: Rails 2
Monday, June 17, 13
Quellen/Literatur
Ruby on Rails
Chad Pytel, Tammer SalehRails Antipatterns - Best practice
Ruby on Rails Refactoring,Addison-Wesley Professional,
2010
Monday, June 17, 13
Ruby on Rails
Konzepte & Design Patterns
Monday, June 17, 13
Model-View-Controller(MVC)
Don’t Repeat Yourself(DRY)
Convention Over Configuration
(COC)
Ruby on Rails
Monday, June 17, 13
Model-View-Controller (MVC)
Ruby on Rails
• Design Pattern zur Strukturierung von Software-Entwicklung
• Entwicklung 1979 für Oberflächen mit Smalltalk
• De-facto-Standard für Grobentwurf vieler komplexer Softwaresysteme
• Ziel: Reduktion der Komplexität und verbesserte Wiederverwendbarkeit, Wartbarkeit, Flexibilität
• Idee: Isolation von Geschäftslogik und Userinterface und Separierung in lose gekoppelte Komponenten
Monday, June 17, 13
Controller
Ruby on Rails
ModelView
ObserverGeschäftslogik?
Ablaufsteuerung
Anzeige / Userinterface Datenhaltung
Monday, June 17, 13
Model
Ruby on Rails
Datenfluss und MVC in Rails
Browser
Webserver
Router
Controller
ViewDB
Rails-App
Ablauf linear
Monday, June 17, 13
Web Application Architecture
RESTRepresentational State Transfer
ROAResource-Oriented Architecture
&
Monday, June 17, 13
Quellen/Literatur
Web ApplicationArchitecture
Fielding, Roy Thomas,Architectural Styles and the Design of Network-based
Software Architectures,Doctoral dissertation,
University of California, Irvine, 2000
Monday, June 17, 13
Quellen/Literatur
Web ApplicationArchitecture
Richardson, L. and Ruby, S.,RESTful Web ServicesO’Reilly Media, 2007
Dix, P.,Service-Oriented Design
with Ruby on Rails,Addison-Wesley Professional, 2010
Monday, June 17, 13
REST
• “REST is an architectural style for distributed hypermedia systems.” - Roy Fielding, 2000
• Ziele:
• Skalierbare Interaktion zwischen Komponenten und größtmögliche Unabhängigkeit
• Allgemeine Schnittstellen
• Zwischenschichten zur Verbesserung von Sicherheit, Latenz und dem Kapseln von Legacy-Systemen
Web ApplicationArchitecture
Monday, June 17, 13
ROA• “The ROA is a way of turning a problem into a RESTful
Webservice.” - L. Richardson, S. Ruby, 2007
• Rückbesinnung auf Ideen, die das Web erfolgreich gemacht haben
• Adressability & URIs
• Resources & Representations
• Statelessness
• Connectedness
• Uniform InterfaceWeb Application
Architecture
Monday, June 17, 13
Was sind Ressourcen?
• Dinge, die als eigene Entität referenziert oder manipuliert werden können
• Beispiele:
• Version 1.3.1 einer Software
• Die aktuelle Version einer Software
• Die nächste Primzahl nach 1024
• Eine Liste von zu behebenden BugsWeb Application
Architecture
Monday, June 17, 13
Adressierbarkeit und URI
• Jede Ressource hat einen URI
• Der URI ist sowohl der Name als auch die Adresse einer Ressource
• Die URI sollte die Ressource beschreiben:
• http://www.example.com/software/releases/1.3.1.tar.gz
• http://www.example.com/software/releases/latest.tar.gz
• http://www.example.com/nextprime/1024
• http://www.example.com/bugs/by-state/openWeb Application
Architecture
Uniform Resource Identifier
Verschiedene Ressourcen,
gleiche Daten
Monday, June 17, 13
Zustandslosigkeit
• Jeder Request muss in völliger Isolation bearbeitet werden können und alle dafür nötigen Informationen mitliefern
• Der Server speichert keinen Client-Zustand, sondern nur Ressourcen-Zustände
• Die vom Server durchgeführte Aktion hängt nicht vom Client-Zustand ab
• Vorteile:
• Caching und Load Balancing vereinfachen sich
• Der Zurück-Button funktioniertWeb Application
Architecture
Monday, June 17, 13
RepräsentationenTeilmengen von Ressourcen-Zuständen
<person><name = “Nils Haldenwang” /><description>...</description>
</person> Web ApplicationArchitecture
Manipulation von Ressourcen durch Austausch von Repräsentationen
Monday, June 17, 13
Einheitliche Schnittstelle“Was soll mit wem getan werden?”
GET /info.txt HTTP/1.1Host: example.com
Zuordnung einer sinnvollen und einheitlichen Semantik zu den HTTP Verben
Web ApplicationArchitecture
Monday, June 17, 13
Semantik der HTTP Verben
GETAnfordern der Repräsenation einer
Ressource
PUT Ersetzt existierende Ressource oder legt neue an übergebener URI an
POST
Annotation existenter Ressourcen, Übergabe von Daten an berechnende Prozesse und Anhängen an vorhandene
Collections
DELETELöscht die angegebene Ressource vom
ServerWeb Application
Architecture
Monday, June 17, 13
HTTP Verben in Rails/ROA
Web ApplicationArchitecture
URI GET PUT POST DELETE
/users Liste aller Nutzer
- Nutzer anlegen
-
/users/3Repräsenta-
tion von Nutzer 3
Update von Nutzer 3
- Nutzer 3 löschen
Monday, June 17, 13
Sicherheit und Idempotenz
Web ApplicationArchitecture
Ressource ändert sich nicht Wiederholte Anwedung ändert nichts
42x0 = 42x0x0x0 = 0
Verb sicher idempotent
GET
PUT
POST
DELETE
Vorteil: Zuverlässige
Anfragen über unzuverlässiges
Netzwerk
Monday, June 17, 13
Nils Haldenwang, B.Sc.
Gastvortrag Datenbanksysteme:
Ruby on Rails
Institut für InformatikAG Medieninformatik1
1Tuesday, June 18, 13
Ruby on Rails
Models mit ActiveRecord
2
2Tuesday, June 18, 13
Ruby on Rails
Model: ORM
Idee: Repräsentiere die Tabelle durch eine Klasse und die Zeilen durch einzelne Instanzen.
id first_name last_name age
1 Nils Haldenwang 25
2 Luke Skywalker 42
Tabelle: users Klasse: User
snake_case
pluralisierter snake_case
3Tuesday, June 18, 13
Migrations
4
Ruby on Rails4Tuesday, June 18, 13
5
Migrations• Ruby DSL zur Definition und Manipulation des
Datenbankschemas
•Datenbankunabhängig (in gewissem Rahmen)
• Inkrementelle Entwicklung der Datenbank
• Kann mit in die Versionskontrolle eingecheckt werden
• Automatische Versionierung
• Gesamtschema in db/schema.rb
Ruby on Rails
5Tuesday, June 18, 13
Beispiel: Tabelle erstellen
6
class CreateUsers < ActiveRecord::Migration
def up create_table :users do |t| t.string :first_name t.string :last_name
t.timestamps end end
def down drop_table :users endend
Ruby on Rails
Anpassungdes Schemas
Anpassungrückgängigmachen
6Tuesday, June 18, 13
Ruby on Rails
class User < ActiveRecord::Baseend
u = User.new first_name: "Obi-Wan", last_name: "Kenobi"u.persisted? # => falseu.saveu.persisted? # => trueputs "#{u.first_name}, #{u.last_name}"# => Obi-Wan Kenobi
obi_wan = User.find_by_first_name("Obi-Wan")puts obi_wan.last_name # => Kenobi
Model: Userapp/models/user.rb DRY
7Tuesday, June 18, 13
Ruby on Rails
Query-API
8
8Tuesday, June 18, 13
Where-Clauses
9
User.create name: "Nils", age: 24User.create name: "Luke", age: 42
User.where(name: "Nils")User.where("name = ?", "Nils")User.where("name = :name", name: "Nils")
User.where(name: "Nils", age: 24)User.where(name: "Nils").where(age: 24)User.where("name = ? AND age = ?", "Nils", 24)
User.where("name = ? OR age = ?", "Nils", 42)
User.where(name: ["Nils", "Luke"]).order("name ASC")
User.where("name LIKE 'L%'")
9Tuesday, June 18, 13
SQL-Injections
10
User.where("name = #{params[:name]}")
Robert’); DROP TABLE Students; --
Obacht!
10Tuesday, June 18, 13
Ruby on Rails
Associations
11
11Tuesday, June 18, 13
1:1-Beziehung: Definition
12
class Avatar < ActiveRecord::Base belongs_to :userend
class User < ActiveRecord::Base has_one :avatarend
Fremdschlüssel: user_id
12Tuesday, June 18, 13
1:1-Beziehung: Anwendung
13
u = User.create name: 'Nils'u.avatar # => nila = Avatar.new url: 'foo.jpeg'a.persisted? # => falseu.avatar = aa.persisted? # => true
u.avatar = Avatar.new url: 'bar.jpeg'
Avatar.all# => [# #<Avatar id: 1, url: "foo.jpeg", user_id: nil>,# #<Avatar id: 2, url: "bar.jpeg", user_id: 1># ]
13Tuesday, June 18, 13
Abhängigkeiten
14
class Avatar < ActiveRecord::Base belongs_to :userend
class User < ActiveRecord::Base has_one :avatar, dependent: :destroyend
14Tuesday, June 18, 13
1:n-Beziehung: Definition
15
class Article < ActiveRecord::Base belongs_to :userend
class User < ActiveRecord::Base has_many :articlesend
Fremdschlüssel: user_id
15Tuesday, June 18, 13
1:n-Beziehung: Anwendung
16
u = User.firstu.articles # => nilu.articles.new title: "Title"# => #<Article id: nil, title: "Title", user_id: 1>u.saveu.articles.first# => => #<Article id: 1, title: "Title", user_id: 1>
u.articles << Article.new( title: "Another Title" )u.articles.count # => 2
u.articles.delete Article.find(1)u.articles.count # => 1
u.articles.clearu.articles.count # => 0
Article.count # => 2
16Tuesday, June 18, 13
n:m-Beziehung: Definition
17
class Article < ActiveRecord::Base has_and_belongs_to_many :tagsend
class Tag < ActiveRecord::Base has_and_belongs_to_many :articlesend
class CreateArticlesTags < ActiveRecord::Migration def change create_table :articles_tags, id: false do |t| t.references :article, null: false t.references :tag, null: false end end
Sortiert17Tuesday, June 18, 13
Ruby on Rails
Validations
18
ActiveRecordGrundlagen
18Tuesday, June 18, 13
Validations: Grundlagen
19
class User < ActiveRecord::Base validates_numericality_of :age validates_presence_of :nameend
u = User.new age: "foo"u.valid? # => falseu.errors[:age] # => "is not a number"u.errors[:name] # => "can't be blank"
19Tuesday, June 18, 13
Validations: Parameter
20
validates_presence_of :name, message: "Y u no use name?"
validates_numericality_of :age, on: :create
validates_length_of :name, within: 6..42
validates :name, presence: true, length: { minimum: 6 }, uniqueness: true
20Tuesday, June 18, 13
Validierung mit Methode
21
class Feed < ActiveRecord::Base validate :valid_feed_url
protected def valid_feed_url result = Feedzirra::Feed.fetch_and_parse(self.url) if result.nil? || result.kind_of?(Fixnum) errors.add(:url, "The feed url was not valid.") end endend
21Tuesday, June 18, 13
Ruby on Rails
Callbacks
22
ActiveRecordGrundlagen
22Tuesday, June 18, 13
Callback-Registrierung
23
class Beethoven < ActiveRecord::Base before_destroy :last_words
protected def last_words logger.info "Friends applaud, the comedy is over." endend
class Beethoven < ActiveRecord::Base before_destroy do logger.info "Friends applaud, the comedy is over." end
before_save(on: create) do logger.info "Here we go." endend
23Tuesday, June 18, 13
Mögliche Callbacks
24
• before_validation, before_validation_on_create
• after_validation, after_validation_on_create
• before_save
• before_create, after_create
• before_destroy, after_destroy
24Tuesday, June 18, 13
Beispiel: Geocoding
25
class Address < ActiveRecord::Base include GeoKit::Geocoders
before_save :geolocate validates_presence_of :street, :city, :state, :zip
def to_s "#{street} #{city} #{state} #{zip}" end
protected def geolocate res = GoogleGeocoder.geocode(to_s) self.lattitude = res.lat self.longitude = res.lng endend
25Tuesday, June 18, 13
Verarbeitung abbrechen
26
def geolocate res = GoogleGeocoder.geocode(to_s) if res.success self.lattitude = res.lat self.longitude = res.lng else errors[:base] = "Geocoding failed. Please check address." false endend
Abbruch der Verarbeitung, wenn ein Callback false liefert
26Tuesday, June 18, 13
Views mit HTML & ERB
27
Ruby on Rails
27Tuesday, June 18, 13
HTML-Gerüst
28
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html> <head> <title>Titel der Webseite</title> <!-- Kommentare werden nicht angezeigt. --> </head> <body> <div id="header" class="container"> <h1>Überschrift</h1> <p>Inhalt <em>der</em> Webseite</p> </div> </body></html>
Ruby on Rails
28Tuesday, June 18, 13
29
Embedded Ruby (ERB)
<div id='user-<%= @user.id %>'> <h2> <%= @user.first_name %> <%= @user.last_name %> </h2> <p>Age: <%= @user.age %></p></div>
Ruby on Rails
Einbetten des Rückgabewertes eines Ruby-Ausdruckes
29Tuesday, June 18, 13
30
ERB und Schleifen
<div id="squares"> <% 1.upto(3) do |i| %> <p> The square of <%= i %> is <%= i*i %>.</p> <% end %></div>
Ruby on Rails
<div id="squares"> <p> The square of 1 is 1.</p> <p> The square of 2 is 4.</p> <p> The square of 3 is 9.</p></div>
Ausführung ohne
Einbettung
30Tuesday, June 18, 13
Controller & Routing
31
Ruby on Rails
31Tuesday, June 18, 13
Ruby on Rails
Controller : UsersController
class UsersController < ApplicationController def show @user = User.find(params[:id]) endend
app/controllers/users_controller.rb
MyRailsApp::Application.routes.draw do get 'users/:id' => "users#show"end
app/config/routes.rb
32Tuesday, June 18, 13
33
RESTful Controller Actions
HTTP Verb URI Action
GET /users index
POST /users create
GET /users/:id show
PUT /users/:id update
DELETE /users/:id destroy
GET /users/new new
GET /users/:id/edit edit
33Tuesday, June 18, 13
Ruby on Rails
Demo: Blog
34
34Tuesday, June 18, 13
35 Ruby on Rails
Anforderungen: Blog
• Ein Blog besteht aus Artikeln
•Artikel gehören zu einer Kategorie
• Ein Artikel kann mit mehreren Schlagworten versehen sein
n
1Category
Article
Tag
n
m
35Tuesday, June 18, 13