{"id":150,"date":"2011-03-08T11:17:26","date_gmt":"2011-03-08T10:17:26","guid":{"rendered":"https:\/\/alistapart.com\/it\/article\/rapid-prototyping-con-sinatra\/"},"modified":"2011-03-08T11:17:26","modified_gmt":"2011-03-08T10:17:26","slug":"rapid-prototyping-con-sinatra","status":"publish","type":"article","link":"https:\/\/alistapart.com\/it\/article\/rapid-prototyping-con-sinatra\/","title":{"rendered":"Rapid prototyping con Sinatra"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/alistapart.com\/it\/wp-content\/uploads\/sites\/2\/2011\/03\/n25sinatra.png\" border=\"0\" width=\"316\" height=\"198\" align=\"left\" \/>Se siete web designer o web developer, avete sicuramente familiarit\u00e0 con il prototyping. Dai grezzi wireframe alla creazione di interfacce in Photoshop, i progettisti fanno la mappatura di come funzioneranno i siti prima di crearli. Negli scorsi anni, il processo di prototipazione \u00e8 cambiato in maniera significativa. Con i produttori di browser che in generale sono d&#8217;accordo sugli standard web e con l&#8217;avvento di tool quali Firebug e web inspector di WebKit, possiamo a volte <a href=\"http:\/\/37signals.com\/svn\/posts\/1061-why-we-skip-photoshop\">evitare Photoshop in toto<\/a> e andare direttamente nel browser. Inoltre, i framework JavaScript come jQuery ci permettono di giocare con gli eventi del browser con poche righe di codice. Ma cosa succede se abbiamo bisogno di fare qualcosa in pi\u00f9? Man mano che i siti web diventano <em>applicazioni<\/em> web, abbiamo bisogno di fare dei prototipi che implementino anche le funzionalit\u00e0 di back-end.<\/p>\n<p>Questo articolo introduce Sinatra, un cosiddetto  \u201cmicro\u201d framework web che ci aiuta nella creazione di web app reali (sebbene semplici) in modo estremamente rapido, permettendoci di fare prototipi dei flussi e dei comportamenti che vorreste integrare nel prodotto finale. Sinatra \u00e8 scritto in Ruby, ma per i nostri obiettivi lo useremo come il \u201ccollante\u201d tra il nostro HTML\/CSS e le funzioni del dominio specifico di Sinatra, cos\u00ec non dovrete imparare pi\u00f9 di qualche semplice metodo per ottenere \u201cHello world.\u201d. In questo articolo, il nostro esempio sar\u00e0 una semplicissima app per Twitter, che prende due username e dice se uno segue l&#8217;altro.<\/p>\n<h3 id=\"blurring_8220front_end8221_and_8220back_end8221_and_the_threshhold_of_8220appness8221\">Rendere indistinti \u201cfront end\u201d e \u201cback end\u201d e la soglia dell&#8217;\u201cappness\u201d<\/h3>\n<p>Sebbene si parli molto di \u201capp\u201d ultimamente, metterei dei paletti tra sito internet ed applicazione web nel punto in cui il contributo di un singolo utente determina il corso degli eventi sullo schermo. Sulle prime, le app potrebbero sembrare semplici da prototipare come successioni di schermate, ma quando si ha effettivamente un app funzionante, saltano sempre fuori delle situazioni impredicibili. Ci potrebbero ad esempio essere diverse homepage per gli utenti loggati e per i nuovi utenti. Un utente potrebbe dover saltare ad un sito di terze parti per l&#8217;autenticazione prima di ritornarvi. Come rendereste tale esperienza il pi\u00f9 invisibile possibile? Una feature must-have potrebbe apparire mentre voi (in qualit\u00e0 di first user) siete frustrati cercando di fare qualcosa. Cominciare a giocare con queste azioni in Sinatra vi permette di esplorare questi problemi fin da subito, riducendo il gap tra il back end ed il front end. Se la vostra app attinge ad API di terze parti piuttosto che da un database, il \u201cback end\u201d diventa essenzialmente un blocco fisso e potete effettivamente usare dei dati <em>reali<\/em> nel vostro mockup invece che fare \u201c<a href=\"http:\/\/en.wikipedia.org\/wiki\/Hard_coding\">hard coding<\/a>\u201d (in cui \u00e8 sempre presente la tentazione di creare gli scenari migliori).<\/p>\n<p>Le app di Sinatra creano delle ottime <a href=\"http:\/\/it.wikipedia.org\/wiki\/Proof_of_concept\">proof of concept<\/a> e dei <a href=\"http:\/\/en.wikipedia.org\/wiki\/Minimum_viable_product\">Minimum Viable Products<\/a>, che a volte possono perfino sbocciare in applicazioni complete. Sono fantastiche anche per abbozzare qualcosa in maniera estremamente rapida durante il notiziario o nelle situazioni virali. Passo spesso alcuni giorni su una rapida app di Sinatra per vedere se una determinata cosa pu\u00f2 essere fatta con una certa tecnologia o se un dato concetto \u00e8 valido prima di buttarmici a tempo pieno. In due parole, Sinatra \u00e8 il coltellino svizzero del web designer. Non ci vuole molto per imparare ad usarlo e risulta comodo per fare prototipi di grossi progetti. Inoltre, va bene quando si ha bisogno di avere una web app funzionante in maniera rapida, senza soffermarsi troppo sul back-end.<\/p>\n<div class=\"paragrafo\">\n<h2>Primi passi<\/h2>\n<p>Per questo tutorial \u00e8 necessario avere installato Ruby. Se siete su un Mac, ecco un&#8217;ottima <a href=\"http:\/\/hivelogic.com\/articles\/compiling-ruby-rubygems-and-rails-on-snow-leopard\">guida<\/a> di Dan Benjamin su come configurare Ruby e RubyGems per Snow Leopard. Su Windows, provate <a href=\"http:\/\/rubyinstaller.org\/\">RubyInstaller<\/a> e su Ubuntu Linux lanciate <code>sudo apt-get install ruby-full<\/code>. Dovrete anche installare RubyGems, il Ruby package manager. RubyGems distribuisce Sinatra e la Twitter gem (una libreria che ci permette di lavorare con le API di Twitter). Dovremo anche usare un po&#8217; la linea di comando, ma solo per installare le librerie e poi per avviare ed arrestare la nostra app, quindi non preoccupatevi se non sapete usare il terminale (tuttavia, se volete un corso accelerato, vi raccomando caldamente lo screencast <a href=\"http:\/\/peepcode.com\/products\/meet-the-command-line\">Meet the Command Line<\/a> di PeepCode). Giusto per sapere dove si trova su Mac OS X: \u00e8 Terminal.app nella cartelletta Utilities all&#8217;interno di Applications. Per gli scopi di questo articolo, denoter\u00f2 il prompt della linea di comando con <code>prompt&gt;<\/code>. Scrivete semplicemente il comando dopo il prompt e premete invio. Qualunque cosa appaia sotto a <code>prompt&gt;<\/code> \u00e8 l&#8217;output di quel comando nel terminale.<\/p>\n<p>Una volta installati Ruby e RubyGems, dovrete aprire Terminal e far partire:<\/p>\n<pre><code>prompt&gt; sudo gem install sinatra twitter\n<\/code><\/pre>\n<p>Ora abbiamo tutte le librerie che ci servono. Una volta fatto ci\u00f2, potete chiudere Terminal.<\/p>\n<\/div>\n<div class=\"paragrafo\">\n<h2>Organizzare una app Sinatra<\/h2>\n<p>Adesso siamo pronti per scrivere la nostra app. Ma prima, qualche parola su come funziona Sinatra. Il framework si basa sul pattern <a href=\"http:\/\/it.wikipedia.org\/wiki\/Model-View-Controller\">MVC<\/a>, in cui un controller si interpone tra un \u201cmodel\u201d ossia un rappresentazione dei dati con cui state lavorando, e la view, che \u00e8 come i dati appaiono nel front-end. Un model \u00e8 solitamente un database, ma pu\u00f2 essere qualunque fonte di dati, come una API o un input dall&#8217;utente memorizzato in un cookie. La cosa importante, tuttavia, \u00e8 che non \u00e8 collegato alla sua rappresentazione sullo schermo (o, nel gergo MVC, la \u201cview\u201d). Un controller parla sia al mode sia alla view per determinare quali dati vengono inviati e dove.<\/p>\n<p>Nel contesto del prototyping, fare un mockup in HTML\/CSS standard costituirebbe la V in MVC, con i dati \u201chardcoded\u201d per scopi dimostrativi. Cominciando a pensare a come il model ed il controller influenzino la view vuol dire arrivare al cuore di cosa rende la vostra nuova cosa una \u201capp\u201d. Il vostro controller pu\u00f2 prendere dei segnali da entrambe i lati e determinare in che modo il dato \u00e8 rappresentato nella view o aggiornato nel model.<\/p>\n<p>Dal momento che Sinatra \u00e8 un \u201cmicro-framework,\u201d in realt\u00e0 fornisce solo la \u201cC\u201d e \u201cV\u201d in MVC. E&#8217; agnostico riguardo a come vi portate il vostro model. I web framework che hanno molte pi\u00f9 funzioni come Ruby on Rails forniscono tutte e tre, perfino con un pesante database layer. Dal momento che prenderemo tutti i nostri dati dalla API di Twitter, il nostro model saranno i dati che ritorner\u00e0: avremo solo bisogno di qualche metodo per richiedere i dati che vogliamo e mandarli al nostro controller.<\/p>\n<p>Come funziona un controller? In Sinatra, \u00e8 semplicemente una lista di <a href=\"http:\/\/tomayko.com\/writings\/rest-to-my-wife\">verbi HTTP<\/a> con istruzioni su cosa fare in risposta a questi verbi. Quando il vostro browser inoltra un comando <code>GET<\/code> ad una app Sinatra con un certo pattern URL, quest&#8217;ultima far\u00e0 qualunque cosa c&#8217;\u00e8 all&#8217;interno del blocco che corrisponde a quel pattern.<\/p>\n<p>Ecco un esempio dell&#8217;app Sinatra pi\u00f9 semplice del mondo.<\/p>\n<p>In testa ad ogni file della app mettiamo le seguenti due righe per far s\u00ec che Ruby sappia che si tratta di una app Sinatra:<\/p>\n<pre><code>require 'rubygems'\nrequire 'sinatra'\n<\/code><\/pre>\n<p>Quindi, la nostra semplice app:<\/p>\n<pre><code>get '\/hello' do\n  \"Hello\"\nend\n<\/code><\/pre>\n<p>Tutto quello che c&#8217;\u00e8 tra il <code>do<\/code> e l&#8217;<code>end<\/code> \u00e8 quello che Sinatra eseguir\u00e0 quando il browser chieder\u00e0 quello specifico URL. In questo caso, se un browser naviga fino a \/hello, mostrer\u00e0 il testo \u201cHello\u201d nel browser. Ecco un esempio un po&#8217; pi\u00f9 interessante:<\/p>\n<pre><code>get '\/hello' do\n  user = params[:user]\n\n  \"Hello \" + user + \"!\"\nend\n<\/code><\/pre>\n<p>In questo esempio stiamo catturando i parametri della query GET per passarli alla nostra app. Se navigate su \/hello?user=Al in questa app, la pagina mostrer\u00e0 \u201cHello Al!\u201d<\/p>\n<p>In alternativa, per URL pi\u00f9 carini, l&#8217;esempio pu\u00f2 essere scritto cos\u00ec:<\/p>\n<pre><code>get '\/hello\/:user' do\n  user = params[:user]\n\n  \"Hello \" + user + \"!\"\nend\n<\/code><\/pre>\n<p>Quindi, navigare su \/hello\/Al vi dar\u00e0 lo stesso risultato. Per far partire questa app, cambiate la sua directory nel Terminal (potete chiamare la app \u201cmyapp.rb\u201d per ora) e poi farla partire:<\/p>\n<pre><code>prompt&gt; ruby myapp.rb\n== Sinatra\/1.0 has taken the stage on 4567 for development with \nbackup from Thin\n&gt;&gt; Thin web server (v1.2.7 codename No Hup)\n&gt;&gt; Maximum connections set to 1024\n&gt;&gt; Listening on 0.0.0.0:4567, CTRL+C to stop\n<\/code><\/pre>\n<p>Ora che il server locale sta andando, provatela facendo puntare il vostro browser all&#8217;indirizzo  http:\/\/localhost:4567\/hello\/Al. Per fermare il server, premete control-C (dovrete fermare e far partire il server se apportate cambiamenti al codice).<\/p>\n<\/div>\n<div class=\"paragrafo\">\n<h2>E la View?<\/h2>\n<p>Questo \u00e8 tutto riguardo all&#8217;aggiunta di un layer di funzionalit\u00e0 ad un mockup statico, quindi come interpoliamo queste cose nell&#8217;effettivo HTML? Usiamo le views. Sinatra rende questa operazione molto semplice cercando i file in una cartella views all&#8217;interno della root della vostra app. In ogni blocco del verbo, si punta ad una specifica view. Ecco lo stesso esempio con una view:<\/p>\n<pre><code>get '\/hello' do\n  @user = params[:user]\n\n  erb :hello\nend\n\n<\/code><\/pre>\n<p>Ora se la vostra app si trova in \/myapp\/myapp.rb nel vostro file system, dovrete mettere la view \u201chello\u201d in \/myapp\/views\/hello.erb. Ecco a cosa assomiglia tale file:<\/p>\n<pre><code>&lt;h1&gt;Hello &lt;%= @user %&gt;!&lt;\/h1&gt;\n<\/code><\/pre>\n<p>Ci sono molte cose qui. La prima cosa che potreste notare \u00e8 che mettiamo un <code>@<\/code> prima della nostra variabile utente. Questo la fa diventare una variabile istanza. Le variabili istanza sono importanti in Ruby ma per i nostri scopi, va bene sapere solo che soltanto le variabili istanza possono essere passate alle views. Se avete alcuni dati all&#8217;interno di un \u201cverb block\u201d che volete mostrare in una view, memorizzateli in una variabile istanza o non faranno quel salto.<\/p>\n<p>Per richiamare la nostra view, usiamo il metodo <code>erb<\/code>. ERB sta per \u201cembedded ruby\u201d: \u00e8 il linguaggio di template che usiamo per interpolare Ruby nel nostro HTML. Mettendo <code>erb :hello<\/code> come ultima riga nel nostro \u201cverb block\u201d, diciamo a Sinatra che vogliamo usare ERB per fare il rendering di un template chiamato \u201chello.erb\u201d all&#8217;interno della cartella views della nostra app. Quando facciamo ci\u00f2, sapr\u00e0 che deve passare tutte le variabili istanza presenti nel nostro block a quella view.<\/p>\n<h3>Lavorare con dati reali: la API di Twitter<\/h3>\n<p>Come vedete, Sinatra rende estremamente semplice creare una web app, se la soglia per la  \u201cappness\u201d \u00e8 quella che pu\u00f2 manipolare gli input dell&#8217;utente. Per renderla una app <em>reale<\/em>, abbiamo bisogno di alcuni dati con cui lavorare. Per questo, tiriamo fuori la Twitter API tramite la Twitter gem. Dopo questa parte del tutorial, avremo un&#8217;ossatura di una app di Twitter che potrete usare per crearvi un bellissimo mockup HTML\/CSS.<\/p>\n<p>Creiamo una nuova cartella chiamata followapp ed un file al suo interno chiamato followapp.rb. In questo file, possiamo usare le stesse istruzioni \u201crequire\u201d di prima, ma ne aggiungeremo un&#8217;altra per includere la libreria Twitter:<\/p>\n<pre><code>require 'rubygems'\nrequire 'twitter'\nrequire 'sinatra'\n<\/code><\/pre>\n<p>In questa app avremo due \u201cazioni\u201d: una pagina index che raccoglier\u00e0 gli utenti di cui vorremo controllare lo stato \u201cfollow\u201d e una pagina dei risultati che mostreranno se l&#8217;utente A segue l&#8217;utente B.<\/p>\n<p>Ecco com&#8217;\u00e8 la nostra azione della index:<\/p>\n<pre><code>get '\/' do\n\n  erb :index\nend\n<\/code><\/pre>\n<p>Dal momento che non stiamo facendo nulla nel back end, tutto quello che dobbiamo fare \u00e8 dire a Sinatra di puntare ad una certa view. In quella view avremo una form che raccoglie i dati dell&#8217;utente e li manda alla nostra altra azione. Ecco com&#8217;\u00e8 il file \/views\/index.erb:<\/p>\n<pre><code>&lt;h1&gt;Enter two users&lt;\/h1&gt;\n\n&lt;form method=\"get\" action=\"\/follows\"&gt;\n  Does &lt;input type=\"text\" name=\"user1\" \/&gt; follow \n  &lt;input type=\"text\" name=\"user2\" \/&gt;? &lt;input type=\"submit\" value=\"Go\" \/&gt;\n\n&lt;\/form&gt;\n<\/code><\/pre>\n<p>Come potrete immaginare, questo li invia tramite GET, creando un URL che somiglia a questo: \/follows?user1=username&amp;user2=username. Per gestirlo, creiamo un&#8217;altra azione nel nostro controller che risponde a tali parametri:<\/p>\n<pre><code>get '\/follows' do\n  @user1 = params[:user1]\n  @user2 = params[:user2]\n\n  #not implemented yet\n  @following = is_following?(@user1, @user2)\n\n  erb :follows\nend\n<\/code><\/pre>\n<p>Questa azione gestisce la risposta. Prende i due parametri che gli diamo dalla pagina index e genera una variabile chiamata <code>@following<\/code> che non abbiamo ancora implementato.<\/p>\n<\/div>\n<div class=\"paragrafo\">\n<h2>Ti seguo se mi segui<\/h2>\n<p>Ecco come implementiamo il core engine della app: il metodo <code>is_following?<\/code>, che scopre se l&#8217;utente uno segue l&#8217;utente due. Twitter non rende semplice controllare esattamente se un utente ne segue un altro, ma hanno un  <a href=\"http:\/\/dev.twitter.com\/doc\/get\/followers\/ids\">followers endpoint<\/a> nella loro API che d\u00e0 come risultato una list di user ID per tutti i follower di un certo account. C&#8217;\u00e8 un problemino nell&#8217;usare questo ed \u00e8 che abbiamo bisogno di ottenere uno user ID dallo screen name per controllarlo nella lista. Perci\u00f2, useremo solo lo <a href=\"http:\/\/dev.twitter.com\/doc\/get\/users\/show\">users\/show endpoint<\/a>. E&#8217; semplice con la Twitter gem. Nella nostra app, ecco il metodo che scriveremo:<\/p>\n<pre><code>def twitter_id(screen_name)\n  Twitter.user(screen_name).id\nend\n<\/code><\/pre>\n<p>Questo prende uno username e restituisce lo user ID. Cos\u00ec, se dovessi lanciare <code>twitter_id(\"a_l\")<\/code>, otterrei 7865282. Ora, abbiamo bisogno solo di un altro metodo, <code>is_following?<\/code>, per confrontare due ID. Ecco com&#8217;\u00e8:<\/p>\n<pre><code>def is_following?(a,b)\n  followers = Twitter.follower_ids(twitter_id(b)).ids\n  followers.include?(twitter_id(a))\nend\n<\/code><\/pre>\n<p>Il metodo <code>Twitter.follower_ids<\/code> restituisce un array di user ID con i follower dello user B. Poi usiamo <code>include?<\/code> per controllare se lo user ID dell&#8217;utente A \u00e8 presente nell&#8217;array. (Per ulteriori dettagli su come funzionano <code>include?<\/code> e gli array, guardate la <a href=\"http:\/\/www.ruby-doc.org\/core\/classes\/Array.html#M000265\">Array documentation<\/a> di Ruby). Quindi, con solo poche righe di codice, abbiamo adesso il kernel della nostra app. (Notate che il metodo <code>Twitter.follower_ids<\/code> restituisce solo i primi 5000 follower dell&#8217;utente. Ci sono modi per ottenerli tutti, ma complicherebbe la app.) Questo ci riporta alla riga nella nostra action:<\/p>\n<pre><code>@following = is_following?(@user1, @user2)\n<\/code><\/pre>\n<p>Questa variabile istanza risponder\u00e0 quindi <code>true<\/code> o <code>false<\/code> a seconda che <code>@user1<\/code> segua <code>@user2<\/code>. Come sar\u00e0 la nostra view? (Questa \u00e8 contenuta in \/followapp\/views\/follows.erb.)<\/p>\n<pre><code>&lt;h2&gt;&lt;%= @user1 %&gt; &lt;%= @following ? \"follows\" : \"does not follow\" %&gt; \n&lt;%= @user2 %&gt;&lt;\/h2&gt;\n<\/code><\/pre>\n<p>Ecco fatto! Questa view mostrer\u00e0 \u201cUsername follows Username\u201d o \u201cUsername does not follow Username.\u201d<\/p>\n<div class=\"illustration full left\"><img decoding=\"async\" src=\"http:\/\/alistapart.com\/it\/wp-content\/uploads\/sites\/2\/2011\/03\/ala_twitter_app_screenshot.png\" border=\"0\" alt=\"I risultati dell'esecuzione della nuova app Twitter.\" \/><\/p>\n<p>Il risultato dell&#8217;esecuzione della nuova app Twitter.<\/p>\n<\/div>\n<p>Ecco l&#8217;intera \u201capp\u201d:<\/p>\n<pre><code>require 'rubygems'\nrequire 'twitter'\nrequire 'sinatra'\n\ndef twitter_id(screen_name)\n  Twitter.user(screen_name).id\nend\n\ndef is_following?(a,b)\n  followers = Twitter.follower_ids(twitter_id(b)).ids\n  followers.include?(twitter_id(a))\nend\n\nget '\/' do\n\n  erb :index\nend\n\nget '\/follows' do\n  @user1 = params[:user1]\n  @user2 = params[:user2]\n\n  @following = is_following?(@user1, @user2)\n\n  erb :follows\nend\n<\/code><\/pre>\n<p>Nota: l&#8217;intero codice di questa app \u00e8 <a href=\"https:\/\/github.com\/ashaw\/ALA-Sample-Sinatra-App\">disponibile su Github<\/a>.<\/p>\n<p>In circa 20 righe di codice abbiamo un web app funzionante che pu\u00f2 fungere da prototipo per un progetto a cui stiamo lavorando. Dal momento che Sinatra rende cos\u00ec semplice costruire queste micro app, possiamo ora prototipare la funzionalit\u00e0 nel modo in cui eravamo abituati a prototipare le decisioni di interfaccia. Vedere le funzionalit\u00e0 in azione rende inoltre molto pi\u00f9 semplice decidere se vale la pena continuare un progetto oppure no. Tutto sembra bellissimo nei comp Photoshop o perfino in HTML perfetto, ma quando si <em>usa<\/em> una app, si pu\u00f2 veramente capire se questa \u00e8 la strada giusta su cui proseguire. Con Sinatra queste decisioni possono essere prese prima piuttosto che pi\u00f9 avanti nel corso del progetto, evitando dei dolorosi cambi di direzione.<\/p>\n<\/div>\n<div class=\"paragrafo\">\n<h2>Mostrate e raccontate<\/h2>\n<p>Una volta che la vostra app \u00e8 \u201cup and running\u201d, vorrete probabilmente condividerla. Ricordatevi come Sinatra parte di default a http:\/\/localhost:4567? Condividere la vostra app all&#8217;interno di una rete locale \u00e8 facile come sostituire localhost con il vostro indirizzo IP interno. Solitamente, questo inizia con 10.0 o 192.168 e lo si trova nelle preferenze di rete. Quindi, per far girare la vostra app all&#8217;interno del vostro ufficio o della vostra VPN, usate http:\/\/localip:4567.<\/p>\n<p>Condividere la vostra app con il mondo su Internet \u00e8 un po&#8217; pi\u00f9 complesso, ma non molto. Il modo in assoluto pi\u00f9 semplice per lanciare (\u201cdeploy\u201d) la vostra app \u00e8 con un servizio come  <a href=\"http:\/\/heroku.com\/\">Heroku<\/a> o <a href=\"http:\/\/www.engineyard.com\/\">Engine Yard<\/a>, che sono host web progettati specificamente per far girare le app Ruby (Rails e Sinatra) e vi metteranno la vostra app \u201cup and running\u201d molto rapidamente e con pochissimo sforzo. Heroku \u00e8 gratis per le piccole app, rendendolo l&#8217;ideale per condividere prototipi e ha un&#8217;interfaccia molto pi\u00f9 semplice. Engine Yard ha pi\u00f9 opzioni, ma \u00e8 abbastanza complesso e non ha piani gratuiti. Sfortunatamente, la maggior parte degli shared hosting al di fuori di questi servizi speciali non sono configurati per ospitare app Ruby, ma \u00e8 possibile che abbiate esperienze diverse.<\/p>\n<p>Sia che si tratti di un prototipo, di un single serving site o di qualcosa di pi\u00f9 complesso, \u00e8 sempre elettrizzante vedere anche la app pi\u00f9 semplice in internet. Aggiungere quella \u201cappness\u201d porta in vita quello che prima erano solo pagine su un server.<\/p>\n<\/div>\n<div class=\"paragrafo\">\n<h2>Passi successivi<\/h2>\n<p>C&#8217;\u00e8 molto di pi\u00f9 in Sinatra di quello che ho trattato qui. Per saperne di pi\u00f9, guardate queste risorse:<\/p>\n<ul>\n<li>La documentazione ufficiale, il <a href=\"http:\/\/sinatra-book.gittr.com\/\">Sinatra Book<\/a><\/li>\n<li>Uno screencast di Peepcode, <a href=\"http:\/\/peepcode.com\/products\/sinatra\">Meet Sinatra<\/a><\/li>\n<li>Uno screencast di <a href=\"http:\/\/www.pragprog.com\/screencasts\/v-aksinatra\/classy-web-development-with-sinatra\">Pragmatic Programmers<\/a> su Sinatra<\/li>\n<\/ul>\n<p>Illustrazioni: {carlok}<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Se siete web designer o web developer, conoscerete sicuramente il \u201cprototyping\u201d. Dai semplici wireframe alla creazione delle interfacce in Photoshop, i designer mappano il modo in cui siti funzioneranno prima di crearli. Negli ultimi anni, il processo di prototipazione \u00e8 cambiato in maniera significativa. Con i produttori di browser che in generale aderiscono agli standard web e con l&#8217;avvento di tool come Firebug e web inspector di WebKit, possiamo a volte saltare Photoshop e andare direttamente nel browser. Inoltre, i framework JavaScript come jQuery ci permettono di giocare con gli eventi del browser usando solo qualche riga di codice. E se dovessimo fare qualcosa di pi\u00f9? Man mano che aumenta il numero di siti web che diventa web app, abbiamo ora bisogno di fare prototipi anche della funzionalit\u00e0 del back-end. Vi mostriamo come Sinatra, un cosiddetto \u201cmicro framework web\u201d, vi pu\u00f2 aiutare a creare delle web app reali (sebbene semplici) in maniera estremamente rapida, facendovi creare il prototipo dei flussi e del comportamento che integrerete nel prodotto finale.<\/p>\n","protected":false},"author":818,"featured_media":7000611,"comment_status":"open","ping_status":"open","template":"","categories":[269,271,39,278],"tags":[],"coauthors":[313],"class_list":["post-150","article","type-article","status-publish","has-post-thumbnail","hentry","category-application-development","category-javascript","category-numero-25-8-marzo-2011","category-workflow-tools"],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/alistapart.com\/it\/wp-json\/wp\/v2\/article\/150","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/alistapart.com\/it\/wp-json\/wp\/v2\/article"}],"about":[{"href":"https:\/\/alistapart.com\/it\/wp-json\/wp\/v2\/types\/article"}],"author":[{"embeddable":true,"href":"https:\/\/alistapart.com\/it\/wp-json\/wp\/v2\/users\/818"}],"replies":[{"embeddable":true,"href":"https:\/\/alistapart.com\/it\/wp-json\/wp\/v2\/comments?post=150"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/alistapart.com\/it\/wp-json\/wp\/v2\/media\/7000611"}],"wp:attachment":[{"href":"https:\/\/alistapart.com\/it\/wp-json\/wp\/v2\/media?parent=150"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/alistapart.com\/it\/wp-json\/wp\/v2\/categories?post=150"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/alistapart.com\/it\/wp-json\/wp\/v2\/tags?post=150"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/alistapart.com\/it\/wp-json\/wp\/v2\/coauthors?post=150"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}