• Keine Ergebnisse gefunden

Gastvortrag Datenbanksysteme: Ruby on Rails

N/A
N/A
Protected

Academic year: 2022

Aktie "Gastvortrag Datenbanksysteme: Ruby on Rails"

Copied!
89
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Nils Haldenwang, M.Sc.

Gastvortrag

Datenbanksysteme:

Ruby on Rails

Kapitel 11

(2)

plattformunabhängige General Purpose Programmiersprache

Veröffentlichung 1995 in Japan

außerhalb Japans bekannt geworden um 2000

Objektorientierung

dynamische Typisierung (Duck Typing)

Garbagecollection

Ruby

(3)

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

(4)

Ruby

Einführung in die Syntax

(5)

Quellen / Literaturempfehlungen

2.2.2 Core API: http://www.ruby-doc.org/core-2.2.2/

Ruby Dokumentation: http://www.ruby-doc.org/

(6)

Quellen / Literaturempfehlungen

Dave Thomas Chad Fowler, Andy Hunt,

Programming Ruby 1.9 & 2.0 Pragmatic Bookshelf, 2013

(7)

Quellen / Literaturempfehlungen

Paolo Perrotta

Metaprogramming Ruby 2 Pragmatic Bookshelf, 2014

(8)

Hello World

puts "Hello World!"

Ausgabe Stringliteral

hello_world.rb

$ ruby hello_world.rb

(9)

local_variable = "Lokale Variable"

@instance_variable = "Instanzvariable"

@@class_variable = "Klassenvariable"

$global_variable = "Globale Variable"

SOME_CONSTANT = "Konstante"

SomeClass # Klassenkonstante

Variablen

(10)

Basisdatentypen

natural_number = 42

natural_number.class # => Fixnum, konstante Zahl float_number = 42.0

float_number.class # => Float, Fließkommazahl string = "Hello World!"

string.class # => String symbol = :hello_world

symbol.class # => Symbol, konstanter String

(11)

Collections: Array

a = []

a = Array.new

a = [42, "foo", nil]

puts a[0] # Ausgabe: 42 puts a.size # Ausgabe: 3 a[0] = 24

(12)

Collections: Hash

h = Hash.new h = {}

h = {

:a => "b", :c => 42, "e" => "f",

42 => "The answer,..."

}

puts h[:a] # Ausgabe: b

puts h[42] # Ausgabe: The answer,..

h[:c] = 73 h = {

a: "b",

Hashrocket wenn keine

Symbole

Doppelpunkt bei Symbolen

(13)

Demo

(14)

Methoden

def say_goodnight(name)

result = "Good night, " + name return result

end

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 result end

def say_goodnight(name)

Klammern optional

Rückgabewert ist der Wert

des letzten Ausdruckes.

Empfohlene Schreibweise

(15)

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

(16)

Bedingte Anweisungen

if !( 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

(17)

Schleifen

i = 42

while i > 0 puts i

i -= 1 end

i = 42

until i == 0 puts i

i -= 1 end

a = [1, 2, 3, 4, 5]

for element in a puts element

end

(18)

Collatz

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;

}

(19)

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 iterations end

Collatz

(20)

def collatz(x) iterations = 0 until x == 1 if x.even?

x /= 2 else

x = 3*x + 1 end

iterations += 1 end

iterations end

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 iterations end

(21)

Blöcke

{ puts "Hello, Block!" } do

puts "Hello, Block!"

puts "Multiple lines."

end

(22)

Blöcke übergeben

call_block { puts "Hello, Block!" } call_block do

puts "Hello, Block!"

end

(23)

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.

(24)

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

(25)

Variablen und Blöcke

def call_block yield

end

var = 42

call_block { var = 73 } puts var

# Ausgabe: 73

(26)

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!

(27)

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

(28)

Schleifen mit Blöcken

3.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

(29)

Demo

(30)

Ruby

Installation

(31)

Ruby installieren

Ruby Version Manager

http://beginrescueend.com/

Ruby Installer

http://rubyinstaller.org/

(32)

Ruby installieren mit RVM

$ rvm install 2.2.2

$ rvm use 2.2.2

$ irb

(33)

Ruby on Rails

(34)

Ruby on Rails

In Ruby geschriebenes Webapplication Framework

Forciert Resource-Oriented Architecture

Erstes Framework seiner Art

Open Source

2005 Veröffentlichung Version 1.0

(35)

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.

(36)

Quellen/Literatur

Sam Ruby, Dave Thomas, David Heinmeier Hansson,

Agile Web Development with Rails, Pragmatic Bookshelf, 2014

(37)

Konzepte & Design

Patterns

(38)

Model-View-Controller (MVC)

Don’t Repeat Yourself

(DRY)

Convention Over Configuration

(COC)

(39)

Model-View-Controller (MVC)

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

(40)

Controller

Model View

Observer

Geschäftslogik?

Ablaufsteuerung

Anzeige / Userinterface Datenhaltung

(41)

Model

Datenfluss und MVC in Rails

Browser Webserver Router

Controller

DB View

Rails-App

Ablauf linear

(42)

Representational State Transfer

REST

Resource-Oriented Architecture

ROA

&

(43)

Quellen/Literatur

Fielding, Roy Thomas,

Architectural Styles and the Design of Network-based Software Architectures,

Doctoral dissertation,

University of California, Irvine, 2000

(44)

Quellen/Literatur

Richardson, L. and Ruby, S., RESTful Web Services

O’Reilly Media, 2007

Dix, P.,

Service-Oriented Design with Ruby on Rails,

(45)

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

(46)

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

(47)

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

(48)

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

Uniform Resource Identifier

Verschiedene Ressourcen, gleiche Daten

(49)

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

(50)

Repräsentationen

Teilmengen von Ressourcen-Zuständen

<person>

<name = “Nils Haldenwang” />

Manipulation von Ressourcen durch Austausch von Repräsentationen

(51)

Einheitliche Schnittstelle

“Was soll mit wem getan werden?”

GET /info.txt HTTP/1.1 Host: example.com

Zuordnung einer sinnvollen und einheitlichen Semantik zu den HTTP Verben

(52)

Semantik der HTTP Verben

GET Anfordern 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

Löscht die angegebene Ressource vom

(53)

HTTP Verben in Rails/ROA

URI GET PUT POST DELETE

/users Liste aller

Nutzer - Nutzer

anlegen -

/users/3

Repräsenta- tion von Nutzer 3

Update von

Nutzer 3 - Nutzer 3

löschen

(54)

Sicherheit und Idempotenz

Ressource ändert sich nicht Wiederholte Anwedung ändert nichts

42x0 = 42x0x0x0 = 0

Verb sicher idempotent GET

PUT POST

Vorteil:

Zuverlässige Anfragen über unzuverlässiges

Netzwerk

(55)

Nils Haldenwang, B.Sc.

Gastvortrag

Datenbanksysteme:

Ruby on Rails

(56)

Models mit ActiveRecord

(57)

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

(58)

Migrations

(59)

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

(60)

Beispiel: Tabelle erstellen

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

Anpassung des Schemas

Anpassung rückgängig

(61)

class User < ActiveRecord::Base end

u = User.new first_name: "Obi-Wan", last_name: "Kenobi"

u.persisted? # => false u.save

u.persisted? # => true

puts "#{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: User

app/models/user.rb DRY

(62)

Query-API

(63)

Where-Clauses

User.create name: "Nils", age: 24 User.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")

(64)

SQL-Injections

User.where("name = #{params[:name]}")

Robert’); DROP TABLE Students; --

Obacht!

(65)

Associations

(66)

1:1-Beziehung: Definition

class Avatar < ActiveRecord::Base belongs_to :user

end

class User < ActiveRecord::Base has_one :avatar

end

Fremdschlüssel: user_id

(67)

1:1-Beziehung: Anwendung

u = User.create name: 'Nils' u.avatar # => nil

a = Avatar.new url: 'foo.jpeg' a.persisted? # => false

u.avatar = a

a.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>

# ]

(68)

Abhängigkeiten

class Avatar < ActiveRecord::Base belongs_to :user

end

class User < ActiveRecord::Base

has_one :avatar, dependent: :destroy end

(69)

1:n-Beziehung: Definition

class Article < ActiveRecord::Base belongs_to :user

end

class User < ActiveRecord::Base has_many :articles

end

Fremdschlüssel: user_id

(70)

1:n-Beziehung: Anwendung

u = User.first

u.articles # => nil

u.articles.new title: "Title"

# => #<Article id: nil, title: "Title", user_id: 1>

u.save

u.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.clear

u.articles.count # => 0

(71)

n:m-Beziehung: Definition

class Article < ActiveRecord::Base has_and_belongs_to_many :tags

end

class Tag < ActiveRecord::Base

has_and_belongs_to_many :articles end

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

(72)

Validations

(73)

Validations: Grundlagen

class User < ActiveRecord::Base validates_numericality_of :age validates_presence_of :name

end

u = User.new age: "foo"

u.valid? # => false

u.errors[:age] # => "is not a number"

u.errors[:name] # => "can't be blank"

(74)

Validations: Parameter

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

(75)

Validierung mit Methode

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

end end

(76)

Callbacks

(77)

Callback-Registrierung

class Beethoven < ActiveRecord::Base before_destroy :last_words

protected

def last_words

logger.info "Friends applaud, the comedy is over."

end end

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."

end

(78)

Mögliche Callbacks

before_validation, before_validation_on_create

after_validation, after_validation_on_create

before_save

before_create, after_create

before_destroy, after_destroy

(79)

Beispiel: Geocoding

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 end

end

(80)

Verarbeitung abbrechen

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 end

end

Abbruch der Verarbeitung, wenn

(81)

Views mit HTML & ERB

(82)

HTML-Gerüst

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

(83)

Embedded Ruby (ERB)

<div id='user-<%= @user.id %>'>

<h2>

<%= @user.first_name %>

<%= @user.last_name %>

</h2>

<p>Age: <%= @user.age %></p>

</div>

Einbetten des Rückgabewertes eines Ruby-Ausdruckes

(84)

ERB und Schleifen

<div id="squares">

<% 1.upto(3) do |i| %>

<p> The square of <%= i %> is <%= i*i %>.</p>

<% end %>

</div>

<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

(85)

Controller & Routing

(86)

Controller: UsersController

class UsersController < ApplicationController def show

@user = User.find(params[:id]) end

end

app/controllers/users_controller.rb

MyRailsApp::Application.routes.draw do get 'users/:id' => "users#show"

app/config/routes.rb

(87)

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

(88)

Demo: Blog

(89)

Anforderungen: Blog

Ein Blog besteht aus Artikeln

Artikel gehören zu einer Kategorie

Ein Artikel kann mit mehreren Schlagworten versehen sein

n 1

Category

Article

Tag

n m

Referenzen

ÄHNLICHE DOKUMENTE

Ein Softwaretest prüft und bewertet Software auf Erfüllung der für ihren Einsatz definierten Anforderungen und misst ihre Qualität.. Tests während der Softwareentwicklung dienen

Ein Softwaretest prüft und bewertet Software auf Erfüllung der für ihren Einsatz definierten Anforderungen und misst ihre Qualität.. Tests während der Softwareentwicklung dienen

Ein Softwaretest prüft und bewertet Software auf Erfüllung der für ihren Einsatz definierten Anforderungen und misst ihre Qualität.. Tests während der Softwareentwicklung dienen

Ein Softwaretest prüft und bewertet Software auf Erfüllung der für ihren Einsatz definierten Anforderungen und misst ihre Qualität.. Tests während der Softwareentwicklung dienen

Ein Softwaretest prüft und bewertet Software auf Erfüllung der für ihren Einsatz definierten Anforderungen und misst ihre Qualität.. Tests während der Softwareentwicklung dienen

Ein Softwaretest prüft und bewertet Software auf Erfüllung der für ihren Einsatz definierten Anforderungen und misst ihre Qualität.. Tests während der Softwareentwicklung dienen

Ein Softwaretest prüft und bewertet Software auf Erfüllung der für ihren Einsatz definierten Anforderungen und misst ihre Qualität.. Tests während der Softwareentwicklung dienen

Ein Softwaretest prüft und bewertet Software auf Erfüllung der für ihren Einsatz definierten Anforderungen und misst ihre Qualität.. Tests während der Softwareentwicklung dienen