of 63/63
Sviluppo web con Ruby on Rails

Sviluppo web con Ruby on Rails - Tanasi · Vede persone e fa cose ... Ruby on Rails - fu? “Ruby on Rails is astounding. Using it ... Rails integra tre tipi di tests:

  • View
    224

  • Download
    0

Embed Size (px)

Text of Sviluppo web con Ruby on Rails - Tanasi · Vede persone e fa cose ... Ruby on Rails - fu? “Ruby...

Sviluppo web con Ruby on Rails

Chi vi parlaChi vi parla Alessandro `jekil` Tanasi

Vede persone e fa cose

Non sviluppa siti web ma ha delle web-esigenze da soddisfare (chi non le ha?)

Senza perdere tempo e nel modo pi efficace possibile

Ruby on Rails

Ruby on Rails - fu?Ruby on Rails - fu?Ruby on Rails is astounding. Using it is like watching a kung-fu movie,where a dozen bad-ass frameworks prepare to beat up the little newcomer only to be handed their asses in a variety of imaginative ways.(Nathan Torkington, O'Reilly Program Chair for OSCON)

Ruby on RailsRuby on RailsRuby on Rails un framework per lo sviluppo

di applicativi web

Basato su Ruby

Open source

Pensato per massimizzare la produttivit

Progettato pensando alla felicit del programmatore

http://rubyonrails.org/screencasts

Perch Rails...

La forza di RailsLa forza di Rails Ruby

Convention over configuration

Best practices: MVC, DRY, Testing

Astrazione (SQL, Javascript, ..)

Integrazione con AJAX e REST

Metodologie agile

InstallazioneInstallazione Interprete Ruby

apt-get install ruby Compilazione dei sorgenti IstantRails su Windows Locomotive su OSX

Ruby on Rails

DBMS

SQLite, MySQL, Postgres e altri Editor di testo

TextMate, jEdit, Scite, NetBeans, Aptana, vim, emacs

Let's go!

Struttura directoryStruttura directoryapp controllers helpers models views layoutsconfig environment.rb routes.rbdb database.yml migrationsliblogpublicscripttestvendor plugins rails

Migrations

MigrationsMigrations Evoluzione del database schema nel tempo

Definite indipendentemente dal DBMS sottostante

script/generate migration

Ogni migrazione numerata e applicata sequenzialmente

La migrazione pu essere reversibile

I dati evolvono con la migrazione

rake db:migrate VERSION=X

EsempioEsempioclass CreateUsers < ActiveRecord::Migration def self.up create_table "users", :force => true do |t| t.string :login, :null => false t.string :email, :null => false t.string :salt, :null => false, :limit => 40 t.string :remember_token t.datetime :remember_token_expires_at t.string :password_reset_code, :limit => 40 t.timestamps end add_index :users, :login add_index :users, :enabled end

def self.down drop_table "users" endend

RakeRakeUtility per lo svolgimento di task

db:migrate

db:sessions:create

doc:app

doc:rails

log:clear

rails:freeze:gems

rails:freeze:edge

rails:update

:test (default task)

:stats

Scaffolding

ScaffoldScaffold Creazione automatizzata dell'interfaccia

web di un dato modello

Utile per strumenti che devono essere usabili da subito e con il minimo sforzo

Possibilit di personalizzazioni

Rapidit di sviluppo

ruby script/generate scaffold antani

Modelli

ActiveRecordActiveRecord Ogni tabella del database mappata con

una classe

I nomi delle tabelle sono al plurale mentre le classi dei modelli sono al singolare

Ogni tabella ha un campo primary key chiamato id

La mappatura permette di eseguire operazioni trattando i dati come oggetti

Permette di definire costrutti e condizioni sui dati

FindersFinders User.find(:all)

User.find(:all, :limit => 10)

Dynamic finders

User.find_all_by_last_name Hanson

User.find_by_age 20

User.find_by_first_name_and_last_name Andreas, Kviby

AssociazioniAssociazionihas_one :credit_card, :dependent => :destroy

has_many :comments, :include => :authorhas_many :people, :class_name => "Person", :conditions => "deleted = 0", :order => "name"has_many :tracks, :order => "position", :dependent => :destroyhas_many :comments, :dependent => :nullifyhas_many :tags, :as => :taggablehas_many :subscribers, :through => :subscriptions, :source => :userhas_many :subscribers, :class_name => "Person", :finder_sql => 'SELECT DISTINCT people.* ' + 'FROM people p, post_subscriptions ps ' + 'WHERE ps.post_id = #{id} AND ps.person_id = p.id ' + 'ORDER BY p.first_name'

ValidazioniValidazioni Regole di validazione del modello che

proteggono l'integrit dei dati

La validazione viene eseguita al salvattaggio e modifica di dati

E' fondamentale che ogni dato sia sempre validato

Es. nomi utente univoci

Es. campi che devono essere solo numerici

ValidatoriValidatori validates_acceptance_of

validate_associated

validates_confirmation_of

validates_each

validates_exclusion_of

validates_format_of

validates_inclusion_of

validates_length_of

validates_numericality_of

validates_presence_of

validates_size_of

validates_uniqueness_of

EsempioEsempioclass User < ActiveRecord::Base

validates_presence_of :login, :email validates_presence_of :password, :if => :password_required? validates_presence_of :password_confirmation, :if => :password_required?

validates_length_of :login, :within => 3..40 validates_length_of :email, :within => 3..100 validates_uniqueness_of :login, :email, :case_sensitive => false validates_format_of :email, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i, :message => "Indirizzo email non valido" validates_format_of :login, :with => /^[\w\d\-\_]+$/, :message => "Sono permessi solo lettere" before_save :encrypt_password has_one :country has_many :photos has_one :profile, :dependent => :nullify

Controller

ActiveControllerActiveController I controller sono classi Ruby in

app/controllers

Ad ogni suo metodo pubblico corrisponde una vista

Gestiscono le azioni che si compiono sui dati

Gestiscono tutte le interazioni logiche

Es. un utente compra un oggetto

Es. un utente si iscrive al sito

Flash messagesFlash messages Permettono di impostare un messaggio da

mostrare all'utente nella gestione di una richiesta e visualizzarlo nella successiva

Varie priorit flash[:notice], flash[:error]

Utilizzati per azioni che richiedono un feedback dopo un submit

Es. Compilazione di un ordine online

Es. Login di un utente

EsempioEsempioclass LinksController < ApplicationController def index @user = User.find_by_id(params[:user_id]) @links = @user.links end def latest n = 10 @links = Link.find(:all, :order => 'created_at ASC', :limit => n) endend

Views

ActionViewActionView Si occupa del rendering della risposta al

client

Rendering basato su template

Permesso l'uso di codice all'interno dei template

Il controller sceglie quale template visualizzare

Le view hanno accesso alle variabili d'istanza (ad es. @pluto)

Tipi di templateTipi di template Rxml genera output XML. Tipicamente

usato per generare feed RSS/Atom

Rhtml genera output HTML

Rjs genera codice Javascript. Utilizzato per AJAX

HTML templateHTML template valuta l'espressione e

stampa l'output

valuta l'espressione e stampa l'output senza un newline a fine riga

valuta l'espressione e non stampa l'output

escaping dell'output

PartialsPartials Parti di una pagina (ad es. footer)

Possono essere inclusi in una o pi pagine

Funzionano come i template

Il loro nome inizia con un underscore

Vengono utilizzate per le parti di codice condivise che devono essere riciclate nell'applicazione

Es. search box

Es. header e footer

LayoutLayout I template del layout si trovano in

/app/views/layout

Il posizionamento di tag permette la visualizzazione delle parti di codice generate

visualizza l'output di una view

Permettono di uniformare il layout del sito e se desiderato di personalizzarlo in alcune sue zone

EsempioEsempio

'rss', :action => 'category', :id => 1 %> Papers

'table' %>

'documents', :action => 'category', :id => 1 %>

'rss', :action => 'category', :id => 2 %> Slides

'table' %>

'documents', :action => 'category', :id => 2 %>

'rss', :action => 'category', :id => 3 %> Videos

Helpers

HelpersHelpers Moduli Ruby che definiscono metodi

disponibili nei template

Evitano duplicazione di codice

Riducono il codice nei template

Per default ogni controller ha un helper corrispondente

Usati per definire le funzionalit comuni

Es. loggato un utente?

Es. pagina successiva

EsempioEsempiomodule ApplicationHelper

# Check if a parameter is nil, if it's print - else print the value. NilPrintCheck def npc(var) if var.nil? or var.empty? return '-' else return var end end

Testing

TestingTesting Test::Unit una libreria Ruby per unit

testing

Rails integra tre tipi di tests:

Uni tests (test sul modello) Integration tests (test di integrazione) Functional tests (test sul controller)

Ogni test deve iniziare per test_

Prima dell'esecuzione di ogni test viene chiamato il medoto setup e alla sua conclusione il metodo teardown

Ogni test contiene una o piu assert

Unit TestingUnit Testing Ogni modello ha il suo unit test in

test/units/test_my_model.rb generato automaticamente alla creazione del modello

Utilizzato per verifcare coerenza di

Modello Validatori Funzioni del modello

E' buona norma testare ogni funzione del modello in particolare quelle custom

EsempioEsempiorequire File.dirname(__FILE__) + '/../test_helper'

class UserTest < Test::Unit::TestCase fixtures :users

def test_password_chars assert_difference 'User.count' do u = create_user(:login => '0aaaaaaaA-_') end assert_no_difference 'User.count' do u = create_user(:login => 'aaaaaaaaaaa+') assert u.errors.on(:login) end end def test_should_create_user assert_difference 'User.count' do user = create_user assert !user.new_record?, "#{user.errors.full_messages.to_sentence}" end endend

Helpers & FixturesHelpers & Fixtures Ogni unit test ha il suo helper

E' possibile utilizzare una fixture che contiene i dati di test che vengono caricati nel database

Dati memorizzati in sintassi YAML

Permette di avere uno storage di dati d'esempio

EsempioEsempioquentin: id: 1 login: quentin email: [email protected] created_at: aaron: id: 2 login: aaron email: [email protected] bio: Aaron is a weird guy created_at:

AssertionsAssertions assert(actual, comment) # Asserts truth

assert_equal(expected, actual, comment)

assert_in_delta(expected_float, actual_float, delta,

message)

assert_match(pattern, string, message)

assert_nil(object, message)/assert_not_nil

assert_raise(Exception, ..., message) { block ... }

assert_difference(expressions, difference = 1, &block)

Functional testsFunctional tests Verificano un'istanza di controller

Simula una richiesta HTTP e controlla la risposta

Fatti per verificare il funzionamento della logica applicativa

EsempioEsempiorequire File.dirname(__FILE__) + '/../test_helper'require 'comments_controller'class CommentsController; def rescue_action(e) raise e end; endclass CommentsControllerTest < Test::Unit::TestCase fixtures :users, :comments def setup @controller = CommentsController.new @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new @request.env['HTTP_HOST'] = "localhost" @request.session[:user] = users(:aaron) end def test_rss get :rss, :id => users(:quentin) assert_response :success assert_select "rss > channel" do assert_select "title", /Recent comments/ assert_select "item", 1 assert_select "item > title", Regexp.new(users(:aaron).login) users(:quentin).comments.first.body end end

AssertionsAssertions assert_response

:success|:redirect|:missing|:error

assert_redirected_to(:controller => blog, :action => list)

assert_template store/index

assert_not_nil assigns(:items)

assert session[:user]

assert_not_nil flash[:notice]

Integration testsIntegration tests Test di integrazione al Rails dispatcher e

tutti i controller

Simula scenari d'uso reali

Inludono le stesse funzionalit dei functional tests

Simulano l'utilizzo dei componenti nella loro globalit

EsempioEsempioclass TracerBulletTest < ActionController::IntegrationTest def test_tracer_bullet get("/mcm/user/login") assert_response :success post("/mcm/user/login", :email => self.mail, :password => self.password) assert_redirected_to :controller => 'mcm/general' follow_redirect! assert_response :success expect_count = contacts(:adam_sandler).jobs.size post("/mcm/contacts/search", :q => 'sandler new york') assert_response :success assert_n_search_results(expect_count) get "/mcm/lists/show/#{list.id}" assert_response :success assert_template 'mcm/lists/show' endend

Running testsRunning tests rake - runs all tests

rake test:units

rake test:functionals

rake test:integration

ruby test/unit/user_test.rb

RCOVRCOV Rcov e` una libreria Ruby per misurare la

copertura data dalle unit tests

Utilizzata per trovare parti rimaste scoperte dai test

# Installation of rcov:gem install rcovruby script/plugin install http://svn.codahale.com/rails_rcovrake test:test:rcov

Internals

RoutingRouting Insime di regole che mappano URL e

parametri in componenti Rails

Le rotte sono definite in config/routes.rb

Se un URL non trova una rotts corrispondente si ottiene un 404

Gli oggetti e i controller possono essere mappati sugli URL per creare ad es. /users/photos/1

MVCMVC

Fonte: Manning - Ruby For Rails Ruby Techniques For Railsvelopers

MVC Request CycleMVC Request Cycle1.Richiesta http://localhost:3000/users/new/1

2.Il server Rails:

1.Invoca il dispatcher

2.Cerca la rotta in routes.rb

3.La rotta di default :controller/:action/:id viene usata se non ne vengono trovate altre

4.Il metodo new chiamato all'interno del controller users che prendo il dato ad id 1 dal modello

3.Viene generato codice HTML dalla vista new.html.erb

4.Rails invia tutto il codice HTML generato al browser

Deployment

DeploymentDeployment Utilizzo di normali web server e CGI

(fastCGI)

Utilizzo di cluster (mongrel) e web server di front end in modalita` proxy (apache)

Utilizzo di tool per il deploy automatico (Capistrano)

Il deploy e il mantenimento potrebbe risultare un tallone d'Achille se non vengono svolti utilizzando procedure corrette e lungimiranti

Best praticesBest pratices Usare SQL solo se strettamente necessario

Mettere meno codice possibile nel controller e cercare di tenere logica nel modello

Accedere ai dati utilizzando l'utente corrente se possibile (ad es. current_user.visits.recent)

Dipendere il meno possibile da librerie e plugin esterni (inluderle nell'applicazione)

Utilizzare ampiamente le unit test

Automatizzare ogni task possibile

Libri

Libri utiliLibri utili Agile Web Development with Rails

Professional Ruby on Rails Wrox

Rails Cookbook O'Reilly

Deploying Rails Applications - Pragmatic Bookshelf

Beginning Ruby on Rails - Wrox

Domande

Slides e contattiSlides e contattiQueste slides sono disponibili su:

http://www.lonerunners.net

Scrivetemi pure!

[email protected]

http://www.lonerunners.net/mailto:[email protected]

Slide 1Slide 2Slide 3Slide 4Slide 5Slide 6Slide 7Slide 8Slide 9Slide 10Slide 11Slide 12Slide 13Slide 14Slide 15Slide 16Slide 17Slide 18Slide 19Slide 20Slide 21Slide 22Slide 23Slide 24Slide 25Slide 26Slide 27Slide 28Slide 29Slide 30Slide 31Slide 32Slide 33Slide 34Slide 35Slide 36Slide 37Slide 38Slide 39Slide 40Slide 41Slide 42Slide 43Slide 44Slide 45Slide 46Slide 47Slide 48Slide 49Slide 50Slide 51Slide 52Slide 53Slide 54Slide 55Slide 56Slide 57Slide 58Slide 59Slide 60Slide 61Slide 62Fine