Questo articolo è stato scritto nel 2009. È qui per ragioni storiche — i dettagli tecnici potrebbero non essere più validi.
🔍
Retrospettiva 2026
Il principale competitor che avevamo identificato nella nostra application — Aardvark — fu acquisito da Google per 50 milioni di dollari nel febbraio 2010, per poi essere chiuso un anno dopo. Quora fu lanciato due mesi dopo il nostro rifiuto e crebbe fino a 300 milioni di utenti mensili. La maggior parte degli altri competitor che avevamo elencato — Yahoo Answers, Google Knol, Mosio — sono morti. E il problema che stavamo cercando di risolvere — “fai una domanda, ottieni una risposta soddisfacente da qualcuno che sa davvero” — oggi lo risolvono i large language model. Noi volevamo che gli umani fossero i neuroni di una mente collettiva. I neuroni, alla fine, sarebbero stati artificiali.
Nel 2007, Antonio Orlando mi propose un’idea: una piattaforma di domande e risposte basata sulla semantica. La chiamammo Bioniqa — bionic Q&A. Non un motore di ricerca — i motori di ricerca scansionano pagine esistenti e le classificano. Questo sarebbe stato un sistema in cui sono le persone a generare i contenuti. Fai una domanda, il sistema la instrada verso la persona giusta, e col tempo impara chi sa cosa, dove, e in che lingua.
Chiamavamo gli utenti “Neuroni” e la conoscenza collettiva “la Mente.” Ogni utente è specializzato — un Neurone in un dominio specifico, una lingua, una zona geografica. Quando sono connessi, le informazioni fluiscono tra loro e il sistema si adatta. Il software avrebbe preso in prestito concetti dalla natura: diversità, adattamento, neuroplasticità. Geografia e lingua sarebbero stati attributi di prima classe, non dettagli secondari.
Subject: Notice to all employees
Date: Tue, 24 Feb 2009 13:06:14 -0500
Dear employees,
Due to the current financial situation caused by the slowdown
of the economy, Management has decided to implement a scheme
to put workers of 40 years of age and above on early retirement.
This scheme will be known as RAPE (Retire Aged People Early).
Persons selected to be RAPED can apply to management to be eligible
for the SHAFT scheme (Special Help After Forced Termination).
Persons who have been RAPED and SHAFTED will be reviewed under the
SCREW programme (Scheme Covering Retired Early Workers). A person
may be RAPED once, SHAFTED twice and SCREWED as many times as
Management deems appropriate.
Persons who have been RAPED can only get AIDS (Additional Income
for Dependents & Spouse) or HERPES (Half Earnings for Retired
Personnel Early Severance).
Obviously, persons who have AIDS or HERPES will not be SHAFTED or
SCREWED any further by Management.
Persons who are not RAPED and are staying on will receive as much
SHIT (Special High-Intensity Training) as possible. Management
has always prided itself on the amount of SHIT it gives employees.
Sincerely,
The Management
(Spero vi siate divertiti :D C’e’ anche una versione USAF del 1997).
Questo articolo è stato scritto nel 2009. È qui per ragioni storiche — i dettagli tecnici potrebbero non essere più validi.
🔍
Retrospettiva 2026
La maggior parte dello stack qui è morto: il .live() di jQuery è stato rimosso nella 1.9, attachment_fu è stato soppiantato da Paperclip e poi da ActiveStorage integrato in Rails (Rails 5.2, 2018). Sia il plugin registry di jQuery che RubyForge hanno chiuso i battenti da anni.
Su VisitaCSA stiamo usando
facebox di
defunkt per mostrare le immagini dei
luoghi in grande.
Facebox e’ un ottimo lightbox generico, perche’ e’ veloce, stabile, si basa su
jQuery e ha un’API davvero pulita.
Ma avevamo bisogno di qualcosa in piu’ di un semplice lightbox di
visualizzazione, perche’ volevamo che i nostri utenti potessero navigare
facilmente tra tutte le immagini, possibilmente senza modificare facebox. La
soluzione si e’ rivelata piuttosto semplice, grazie anche al plugin
will_paginate che stavamo
gia’ usando. In sostanza si tratta di avere:
Un model Photo, attrezzato con il metodo has_attachment
Route per le risorse photos (map.resources :photos, :only => :show in
config/routes.rb)
Un metodo show nel controller PhotosController che chiama .paginate
con un argomento :per_page di 1
Una vista HTML per la risorsa photo, con i controlli di paginazione usando
l’helper will_paginate
Del codice jQuery che si aggancia ai link di paginazione e fa caricare al
browser via AJAX la foto successiva direttamente nel facebox.
Ecco il codice rilevante, semplificato rispetto a quello effettivamente
online, perche’ il model photo e’ in realta’ polimorfico (usa STI) e diverse
collezioni sono gestite dal photos controller (foto, volantini, ecc.) per
diversi model, con miniature diverse :P.
classPhotosController<ApplicationControllerlayoutnilbefore_filter:find_place# The photo gallery core is heredefshowphoto=Photo.find(params[:id])page=params[:page]||@place.photos.index(photo)+1@photos=@place.photos.paginate(:per_page=>1,:page=>page)@photo=@photos.firstenddeffind_place@place=Place.find(params[:place_id])endend
vartheLoadSequenceToRunAfterTheDocumentHasBeenLoaded=function(){// The blinking border
//
(function(t){// (C) 2009 vjt <segmentation-fault@core-dumped.info>
var$=function(_){return(document.getElementById(_));};varee=[$('n'),$('s'),$('w'),$('e')],e,_=true;setInterval(function(){for(vari=ee.length;i&&(e=ee[--i]);_){e.className=e.className?'':'b';}},t*08);/* .oOo.oOo.oOo. ^^^^^ -*** * *** *** *******- **/})((4+8+15+16+23+42)*Math.PI/Math.E+42/*166.81*/);// Google analytics
//
try{varpt=_gat._getTracker("UA-1123581-3");pt._trackPageview();}catch($aMarvellousErrorThatWontBeDisplayedOnTheUserBrowserAtAll){}}// end of theLoadSequenceToRunAfterTheDocumentHasBeenLoaded routine
Per me sembra una melodia contorta, o una poesia complicata. E’ ingegneria
malvagia, lo so. Ma mentre lo scrivevo, provavo esattamente la stessa
sensazione di quando scrivevo versi in rima. Le parole di
_why sono assolutamente pertinenti qui:
finche’ i programmatori non smetteranno di comportarsi come se l’offuscamento
fosse moralmente pericoloso, non saranno artisti, solo ragazzini che non
vogliono che il loro cibo si tocchi.
Puoi vedere il codice con l’evidenziazione della sintassi su
github, oppure con la funzione “Visualizza
sorgente” del tuo browser mentre sei sul sito
segfault. :)
Questo articolo è stato scritto nel 2009. È qui per ragioni storiche — i dettagli tecnici potrebbero non essere più validi.
🔍
Retrospettiva 2026
Il sito opensource.org è stato ridisegnato diverse volte dal 2009, e il mirror italiano su opensource.antifork.org non esiste più da un pezzo. L’approccio basato su wget descritto qui non produrrebbe più una copia utilizzabile di un sito moderno pieno di JavaScript.
Attualmente mantengo il mirror italiano del
sito web della Open Source Initiative, e oggi mi sono
reso conto che lo script che avevo scritto qualche mese fa non stava facendo
bene il suo lavoro… perche’ i file CSS non venivano scaricati affatto,
causando un rendering del sito piuttosto sgradevole.
Per fare il mirror di opensource.org sto usando il caro vecchio GNU
Wget con -r –mirror e compagnia bella.
Mentre il buon vecchio wget scarica tutti i prerequisiti di ogni pagina
definiti nel sorgente HTML, non supporta le regole CSS @import e non scarica le
immagini referenziate nei CSS con le regole url().
Comunque, niente che non si possa risolvere con un po’ di regex-fu: ecco
perche’ condivido lo script che sto usando
attualmente per fare il mirror del sito opensource.org, sperando che generi un
nuovo mirror o qualche spunto su come fare meglio questo lavoro :).
Questo articolo è stato scritto nel 2009. È qui per ragioni storiche — i dettagli tecnici potrebbero non essere più validi.
🔍
Retrospettiva 2026
Il plugin permalink_fu è stato abbandonato da oltre un decennio. Rails ha eliminato l’intero sistema di plugin in Rails 4 (2013) – la gem friendly_id è diventata il sostituto standard per gli URL slug.
Un altro spin-off dal sito www.visitacsa.it: un
miglioramento a
permalink_fu che
permette permalink dinamici. Lo so che è un
ossimoro, perché i permalink dovrebbero
essere… beh… permanenti! E siccome i motori di
ricerca li indicizzano, non dovrebbero
mai cambiare. Ma cosa succede quando pubblichi qualcosa, il tuo permalink
viene generato con permalink_fu usando il titolo del tuo post, e dopo un
paio di giorni vuoi cambiare il titolo, e anche il permalink sotto il quale il
post è accessibile?
Seguendo la
specifica, la tua
applicazione dovrebbe inviare uno status HTTP 301 moved permanently quando si
accede al vecchio permalink e fare redirect del client verso il nuovo Uniform
Resource Locator. Questo è più o meno quello che fa la mia modifica a
permalink_fu: ogni volta che gli attributi del tuo post vengono modificati, il
permalink precedente e quello nuovo vengono salvati nel database, e puoi
abilitare il tuo controller a generare redirect 302 moved temporarily quando
necessario. In altre parole, controlla se l’URL richiesto è un vecchio
permalink e reindirizza automagicamente il client verso quello nuovo.
Tutto avviene dietro le quinte, e il plugin ha anche dei comodi task rake per
impostare il model Redirect e le migration associate. E puoi anche cambiarne
il nome, ovviamente! :)
Questo articolo è stato scritto nel 2009. È qui per ragioni storiche — i dettagli tecnici potrebbero non essere più validi.
🔍
Retrospettiva 2026
Questo plugin si basava su $.browser (rimosso in jQuery 1.9) e sul trucco dell’era Prototype di nascondere un file input sotto il cursore. I browser moderni supportano la File API, l’upload drag-and-drop, e input.click() funziona ovunque ormai – niente più inseguimento del mouse.
Di recente ho scritto un plug-in jQuery che
permette l’upload di file via AJAX senza usare un pulsante file input
fisso. Raggiunge il suo scopo installando un handler OnMouseMove sugli elementi
selezionati e spostando il pulsante input sotto il cursore del mouse.
La citazione che ha ispirato questo codice e’: “Se Maometto non va alla
montagna, la montagna va da Maometto”, il contrario del proverbio piu'
noto :).
// ~ JavaScript Kung-FU, with an excess chunky bacon dose! ~
// This plugin allows seamless ajax file uploads without having
// a fixed file input button. It achieves this by installing an
// OnMouseMove handler over the interested elements, and moving
// the input button under the cursor. <<If Muhammad won't go to
// the the mountain, the mountain will come to Muhammad.>> :-).
//
// This approach is needed on the majority of browser, except
// Safari, on which the coder is allowed to trigger a "click"
// event onto an input type=file element. On other browsers,
// you can not, that's why the complicated mousemove approach
// was chosen.
//
// Either way, when the value of the input type=file changes,
// handlers are disabled, and a user-provided callback is then
// called (passed via the "upload" option). Handlers are then
// re-enabled again when the upload succeeds or fails.
//
// IE has additional problems, because, quite unexplicably,
// when submitting a form that causes a page load, the change
// event on the file input is triggered AGAIN, thus triggering
// a new file upload. To circumvent this, you can pass a "linked"
// option, that contains the jQuery selector of the form, and
// whenever an input under this form is hovered, ajax upload
// handlers are temporarily cleared and thus the spurious form
// submission.
//
// The jquery Form plugin is a perfect companion of this one,
// because of its .ajaxSubmit method. Have a look at its home
// page: http://malsup.com/jquery/form/.
//
// Have fun!
// - vjt@openssl.it
//
$.fn.ajaxFormUpload=function(options){varpositioning={top:0,left:0,position:'absolute',cursor:'pointer','z-index':2};varform=$(options.form||'#ajax_upload');form.css(positioning)varinput=form.find('input[type=file]');input.css($.extend(positioning,{width:'10px',opacity:0,'font-size':'0px'}));varhovering_element=null;varelements=$(this);varhandler,event_;if($.browser.safari){event_='click',handler=function(){hovering_element=$(this);input.click();};}else{event_='mousemove',handler=function(event){hovering_element=$(this);form.css({left:event.pageX-10,top:event.pageY-5});};}functionenable(){$(elements).bind(event_,handler);}functiondisable(){$(elements).unbind(event_,handler);}input.change(function(){varelement=hovering_element;if(!element)return;disable();options.upload(element,form);enable();});enable();if(options.linked){$(document).ready(function(){$(options.linked).find('input').mouseover(function(){hovering_element=null;});});}};
È il pesce combattente del Siam, un
bellissimo pesce tropicale, ma con una caratteristica interessante: è
estremamente aggressivo. La credenza popolare vuole che due maschi si combattano
anche in natura, ma non è proprio vero. Questa credenza deriva dal comportamento
del pesce in acquario, dove il vincitore attacca continuamente il perdente,
causandone alla fine la morte.
Ora, pensate all’ecosistema software come a un acquario. E pensate a Microsoft
dentro questo acquario. L’ultima release del sistema operativo Microsoft ha un
pesce aggressivo come skin predefinita, ed è solo in questo acquario. E non c’è
posto per nessun altro: combatteranno qualsiasi avversario, anche se della
stessa specie.
Quel che è incerto è… ci riusciranno, o no? :). Staremo a vedere!
Questo articolo è stato scritto nel 2008. È qui per ragioni storiche — i dettagli tecnici potrebbero non essere più validi.
🔍
Retrospettiva 2026
Apple ha rimosso AU Lab dagli strumenti per sviluppatori Xcode intorno al 2019, e Soundflower è stato abbandonato da Cycling ‘74 (acquisita da Ableton). Il sostituto moderno è BlackHole – un driver audio virtuale che fa lo stesso lavoro.
La sessione a destra mostra un documento aperto su un dispositivo audio aggregato tra soundflower (2 canali) e una Creative SBLive con 6 canali: il flower riceve l’input audio da iTunes e lo indirizza ai canali della scheda, usando tutti e 6 gli speaker.
Sono stati aggiunti degli effetti per migliorare l’esperienza audio (dettagli qui: http://www.rottenbrains.com/?p=232). La sessione a destra usa anche AUNetSend per streamare l’audio verso la sessione a sinistra, connessa agli speaker integrati del MacBook.
Risultato: audio stereo riprodotto su otto canali. Le Audio Units sono uno strumento davvero potente, ben scritto e ben funzionante.
[grazie a nextie per avermi detto di AUNetSend e AUNetReceive]
Miglioramento: non c’è bisogno di usare NetSend e NetReceive per riprodurre su 8 speaker: un dispositivo aggregato composto da Soundflower 2ch, la SBLive USB a 6 canali e l’uscita Built-in è sufficiente!