Ruby & Ruby on Rails for arkitekter. Kim Harding Christensen

64  Download (0)

Full text

(1)

Ruby & Ruby on Rails

for arkitekter

Kim Harding Christensen

(2)

Agenda

Intro & problemstilling

Introduktion til Ruby

DSL’er

Introduktion til Ruby on Rails

Begreber (MVC & REST)

(3)
(4)
(5)

Software udvikling er

for svært og tager al for

lang tid

(6)

.NET 3.0

Problemområde

[Distribuerede

informationssystemer]

(7)

Infosets + Objects + Tuples

=

(8)
(9)
(10)

When I work in Java, I wouldn't say I feel joy.

I don't feel like I'm riding a fast stallion through beautiful

wooded hills, the wind in my long, flowing hair.

I feel more like I'm struggling to convince a workhorse

to pull a plow.

(11)

“Java is the blunt scissors of programming.

It’s what we give to children to program”

(12)

Problemområde

Sprog

(13)

Introduktion til Ruby

(på 10 slides)

I have a lot of trouble writing about Ruby, because I find there's nothing to say. It's why I

almost never post to the O'Reilly Ruby blog. Ruby seems so self-explanatory to me. It

makes it almost boring; you try to focus on Ruby and you wind up talking about some

problem domain instead of the language. I think that's the goal of all programming

(14)

Ruby

Pure Object-Oriented

Language

Dynamisk type system

Simpel nedarvning +

mixins

Block, closures,

continuations

Read-eval-print

Meta-programmering,

metaklasser,

introspection, eval

Simpel & konsistent

syntaks

Regulære udtryk

Cross-platform

(15)

class

MyClass

@instance_var

@@class_var

def

instance_method(arg) ...

end

def

self.class_method(arg) ...

end

def

foo() # getter

@foo

end

def

foo=(value) # setter

@foo = value

end

def

state_changing_method!() ...

end

def

query_method? ...

end

(16)

class

LinkedList

class

Node

def

initialize(element)

@element = element

end

def

element()

@element

end

def

next()

@next

end

def

next=(node)

@next = node

end

end

def

add(element)

...

end

(17)

class

LinkedList

class

Node

def

initialize(element)

@element = element

end

def

element()

@element

end

def

next()

@next

end

def

next=(node)

@next = node

end

end

def

add(element)

...

end

class

Node

attr_reader :element

attr_accessor :next

def

initialize(element)

@element = element

end

end

(18)

class

LinkedList

class

Node

...

end

def

add(element)

node = Node.new(element)

if

(@first == nil)

@first = node

end

if

(@last != nil)

@last.next = node

end

@last = node

end

end

(19)

class

LinkedList

class

Node

...

end

def

add(element)

node = Node.new(element)

if

(@first == nil)

@first = node

end

if

(@last != nil)

@last.next = node

end

@last = node

end

end

class

LinkedList

class

Node

...

end

def

add(element)

node = Node.new(element)

@first = node

unless

@first

@last.next = node

if

@last

@last = node

end

end

(20)

Block & Closures

a = 7

(21)

Block & Closures

def

twice()

yield

yield

end

twice()

{ puts “Hello” }

a = 7

(22)

class

LinkedList

def

add(element)

...

end

def

each()

if

block_given?

node = @first

while

node

do

yield

node.element

node = node.next

end

end

self

end

end

> l = LinkedList.new

> [1,2,3,4,5].each {|e| l.add e}

> l.each {|e| puts e}

1

2

3

4

5

>

(23)

Nedarvning

class

Collection

def

size()

count = 0

self.each {|e| count += 1}

count

end

end

class

LinkedList < Collection

def

add(element)

...

end

def

each()

...

end

end

(24)

Moduler & Mixins

module

Enumeration

def

select()

result = Array.new

this.each {|e| result << yield(e)}

result

end

def

detect() ... end

def

reject() ... end

def

collect() ... end

...

(25)

class

Collection

include Enumeration

def

size()

count = 0

self.each {|e| count += 1}

count

end

end

class

LinkedList < Collection

def

add(element) ...

end

alias

:<< :add

def

each() ...

end

end

(26)

Metode lookup

module Kernel

module M

b = B.new

class Object

include Kernel

end

class A

include M

end

class B < A

(27)
(28)

DSL

Ekstern DSL

Intern DSL

(29)

Rake - Ruby Make

Rakefiler er skrevet i standard Ruby - ingen

behov for XML filer

Tasks med afhængigheder

Rule patterns

Rake består af en fil: 400-500 linier Ruby

kode

http://rake.rubyforge.org

(30)

file 'main.o' => ["main.c", "greet.h"]

do

sh "cc -c -o main.o main.c"

end

file 'greet.o' => ['greet.c']

do

sh "cc -c -o greet.o greet.c"

end

file "hello" => ["main.o", "greet.o"]

do

sh "cc -o hello main.o greet.o"

end

(31)

require

'rake/clean'

CLEAN.include('*.o')

CLOBBER.include('hello')

task :default => ["hello"]

SRC = FileList['*.c']

OBJ = SRC.ext('o')

rule '.o' => '.c'

do

|t|

sh "cc -c -o #{t.name} #{t.source}"

end

file "hello" => OBJ

do

sh "cc -o hello #{OBJ}"

end

# File dependencies go here ...

file 'main.o' => ['main.c', 'greet.h']

file 'greet.o' => ['greet.c']

(32)
(33)

“Full stack” web framework

MVC baseret

“Opinionated”

“Convention over configuration”

Open Source

(34)

Model - View - Controller

Controller

Model

View

DB

1

2

3

4

(35)

Rails MVC

Controller

Model

View

DB

(36)

Rails MVC

Controller

Model

View

DB

Routing

http://kimharding.com/kursus/index.html

(37)

Rails MVC

Controller

Model

View

DB

Routing

http://kimharding.com/kursus/index.html

KursusController.index()

(38)

Rails MVC

Controller

Model

View

DB

Routing

http://kimharding.com/kursus/index.html

KursusController.index()

@kurser = Kursus.find(:all)

(39)

Rails MVC

Controller

Model

View

DB

Routing

http://kimharding.com/kursus/index.html

KursusController.index()

@kurser = Kursus.find(:all)

index.rhtml

(40)

Rails MVC

Controller

Model

View

DB

Routing

http://kimharding.com/kursus/index.html

KursusController.index()

@kurser = Kursus.find(:all)

index.rhtml

<h1>Kurser</h1>

<% @kurser.each do |kursus| %>

<h2><%= @kursus.titel() %></h2>

(41)

ActiveRecord

“The essence of an Active Record is a Domain Model in

which the classes match very closely the record structure of

an underlying database. Each Active Record is responsible

for saving and loading to the database and also for any

domain logic that acts on the data...

The data structure of the Active Record should exactly

match that of the database: one field in the class for each

column in the table...”

Patterns of Enterprise Application Architecture

Martin Fowler

(42)

Analyse model

title

description

logo_url

Brand

title

description

image_url

ProductType

title

price

Product

*

1

*

title

Category

*

*

children

(43)

DB Design

description

id

logo_url

title

varchar(256)

varchar(512)

varchar(80)

int

BRANDS

int

product_type_id

price

id

title

number(8,2)

varchar(80)

int

PRODUCTS

int

brand_id

description

id

image_url

title

varchar(256)

varchar(512)

varchar(80)

int

PRODUCT_TYPES

product_types_id

category_id

int

int

CATEGORIES_PRODUCT_TYPES

id

title

varchar(80)

int

CATEGORIES

(44)

description

id

logo_url

title

varchar(256)

varchar(512)

varchar(80)

int

BRANDS

int

product_type_id

price

id

title

number(8,2)

varchar(80)

int

PRODUCTS

int

brand_id

description

id

image_url

title

varchar(256)

varchar(512)

varchar(80)

int

PRODUCT_TYPES

product_types_id

category_id

int

int

CATEGORIES_PRODUCT_TYPES

parent_id

int

id

title

varchar(80)

int

CATEGORIES

class

CreateBrands < ActiveRecord::Migration

def

self.up

create_table :brands

do

|t|

t.column :title, :string, :null => false

t.column :description, :text

t.column :logo_url, :string

end

end

def

self.down

drop_table :brands

end

end

(45)

class Brand < ActiveRecord::Base

has_many :product_types

end

class ProductType < ActiveRecord::Base

belongs_to :brand

end

title

description

logo_url

Brand

title

description

image_url

ProductType

title

price

Product

*

1

*

title

Category

*

*

parent

children

(46)

class ProductType < ActiveRecord::Base

belongs_to :brand

has_many :products, :dependent => true

end

class Product < ActiveRecord::Base

belongs_to :product_type

end

title

description

logo_url

Brand

title

description

image_url

ProductType

title

price

Product

*

1

*

title

Category

*

*

parent

children

(47)

class ProductType < ActiveRecord::Base

belongs_to :brand

has_many :products

has_and_belongs_to_many :categories

end

class Category < ActiveRecord::Base

has_and_belongs_to_many :product_types

end

title

description

logo_url

Brand

title

description

image_url

ProductType

title

price

Product

*

1

*

title

Category

*

*

parent

children

(48)

title

description

logo_url

Brand

title

description

image_url

ProductType

title

price

Product

*

1

*

title

Category

*

*

parent

children

class Category < ActiveRecord::Base

has_and_belongs_to_many :product_types

acts_as_tree :order => "title"

end

(49)
(50)

Hvad er REST?

“Representational State Transfer is intended to evoke an

image of how a well-designed Web application behaves: a

network of web pages (a virtual state-machine), where

the user progresses through an application by selecting

links (state transitions), resulting in the next page

(representing the next state of the application) being

transferred to the user and rendered for their use.”

Dr. Roy Fielding

(51)

Principper

Applikationstilstand og funktionalitet realiseres vha.

ressourcer

Enhver ressource kan adresseres vha. en URI

Alle ressourcer benytter samme uniforme interface

til at flytte tilstand mellem klient og ressource

Veldefineret sæt af operationer

Veldefineret sæt af content-typer

En protokol som er Client/Server, Stateless &

Cacheable

(52)

REST & HTTP

HTTP benyttes ofte som fundament for REST

Client/Server, Stateless & Cacheable

Ressourcer identificeres af URLs

Operationer er GET, PUT, POST, DELETE

(TRACE, OPTIONS, HEAD)

GET: hent ressource repræsentation

PUT: opdater ressource

POST: opret ny ressource

(53)

Eksempel

Customer

Order

(54)

Eksempel

Customer

Order

OrderLine

Product

GET: list all customers

POST: add new customers

/customers

GET: get customer details

PUT: update customer

DELETE: delete customer

/customers/{id}

(55)

Eksempel

Customer Order

OrderLine Product

GET: list all customers

POST: add new customers

/customers

GET: get customer details

PUT: update customer

DELETE: delete customer

/customers/{id}

GET: get order list

/customers/{id}/orders

GET: get order details

PUT: update order

/orders/{id}

GET: list all orders

POST: add new order

(56)

Rails Demo

Blog app

Baseret på REST

RSS feed

(57)

Rails Demo

Posting

Comment

(58)

Rails Demo

Posting

Comment

*

GET: list all postings {HTML & RSS}

POST: add new posting

(59)

Rails Demo

Posting

Comment

*

GET: list all postings {HTML & RSS}

POST: add new posting

/postings

GET: get post details

PUT: update posting

DELETE: remove posting

(60)

Rails Demo

Posting

Comment

*

GET: list all postings {HTML & RSS}

POST: add new posting

/postings

GET: get post details

PUT: update posting

DELETE: remove posting

/postings/{id}

GET: list all comments

POST: add new comment

(61)

Rails Demo

Posting

Comment

*

GET: list all postings {HTML & RSS}

POST: add new posting

/postings

GET: get post details

PUT: update posting

DELETE: remove posting

/postings/{id}

GET: get comment details

PUT: update comment

DELETE: remove comment

/postings/{id}/comments/{id}

GET: list all comments

POST: add new comment

(62)

From what I have seen so far, Rails is a hyper-productive

agile environment that EVERYONE should be taking very

seriously. It seems to me that a Rails team could leave a

Java or .NET team in the dust by a factor of five or so. I

know the rebuttal to that will be the dreaded "E" word. My

response to that is: "It's OK with me if you want to go

slow, just get out of the way while the rest of us get stuff

done."

(63)
(64)

Kim Harding Design Aps

Kurser i .NET, Java, Ruby, Modellering,

Arkitektur

Mentoring & Reviews

Kontakt:

khc@kimharding.com

Figure

Updating...

References

Related subjects :