<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>El Futirifoken</title>
	<atom:link href="http://www.gazer.com.ar/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.gazer.com.ar</link>
	<description>El arte de no decir nada ;-)</description>
	<lastBuildDate>Wed, 08 Sep 2010 16:59:12 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Procesando archivos en background con Rails</title>
		<link>http://www.gazer.com.ar/2010/09/08/procesando-archivos-en-background-con-rails/</link>
		<comments>http://www.gazer.com.ar/2010/09/08/procesando-archivos-en-background-con-rails/#comments</comments>
		<pubDate>Wed, 08 Sep 2010 16:42:29 +0000</pubDate>
		<dc:creator>Gazer</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[ruby on rails]]></category>

		<guid isPermaLink="false">http://www.gazer.com.ar/?p=1297</guid>
		<description><![CDATA[Procesar archivos en paneles de administración es un bajón, sobre todo cuando son cada vez más grande y cada vez más. En uno de nuestros proyectos tenemos ya unos cinco archivos CSV diferentes a procesar donde cada uno cumple alguna función específica. Algunos de estos archivos superan los 5 Mb por upload, por lo que [...]]]></description>
			<content:encoded><![CDATA[<p>Procesar archivos en paneles de administración es un bajón, sobre todo cuando son cada vez más grande y cada vez más. En uno de nuestros proyectos tenemos ya unos cinco archivos CSV diferentes a procesar donde cada uno cumple alguna función específica. Algunos de estos archivos superan los 5 Mb por upload, por lo que se hizo necesario desacoplar el procesamiento del archivo del request que realiza el upload.</p>
<p>Para manejar procesos en background en rails hay muchas opciones buenas, algunas más complejas con colas de trabajo, workers distribuidos y otras cosas que nosotros no necesitamos. Lo importante para nosotros era encontrar alguno que permita :</p>
<ul>
<li>Procesar en background (obvio <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> )</li>
<li>Poder saber en que estado está el trabajo (% completado)</li>
<li>Al menos un proceso en background a la vez (si hay más que espere su turno, los uploads son semanales o mensuales por lo que no hay tanto solapamiento entre tareas como para justificar múltiples workers)</li>
</ul>
<p>Y nada más. Buscando y buscando caí con <a href="http://github.com/ncr/background-fu">BackgroundFu</a> que cumplía con lo necesario.</p>
<h3>Procesando los archivos</h3>
<p>Como todos los archivos son de texto con algún separador (algunos &#8216;;&#8217;, otros tabs o comas) empezamos por lo básico y crear una clase base que maneje algunos parámetros comunes.</p>
<p>En <a href="http://github.com/ncr/background-fu">BackgroundFu</a> uno puede encolar cualquier clase, por lo que nuestro worker es simplemente una clase con un método <code>process</code> (que también es arbitrario el nombre, podría ser cualquier otro).</p>
<p>Como el archivo que sube el usuario está en un directorio temporal, antes de mandar al proceso en background en necesario guardarlo en algún lugar seguro, para poder saber que al momento de procesarlo va a seguir estando, para ello encapsulamos este comportamiento en un método especial para encolar.</p>
<p>Nuestra completa termina siendo algo como (más adelante veremos en detalle algunas cosas) :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> FileWorker
  <span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#6666ff; font-weight:bold;">BackgroundFu::WorkerMonitoring</span>
&nbsp;
  attr_reader <span style="color:#ff3333; font-weight:bold;">:total_lines</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">enqueue</span><span style="color:#006600; font-weight:bold;">&#40;</span>file, <span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span>
    filename = <span style="color:#996600;">&quot;#{RAILS_ROOT}/tmp/#{self.name}-#{Time.now.to_i}&quot;</span>
    <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>filename, <span style="color:#996600;">&quot;wb&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span> f.<span style="color:#9900CC;">write</span><span style="color:#006600; font-weight:bold;">&#40;</span>file.<span style="color:#9900CC;">read</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
    Job.<span style="color:#9900CC;">enqueue</span>!<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">name</span>, :<span style="color:#996600;">'process'</span>, filename, <span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">id</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> process<span style="color:#006600; font-weight:bold;">&#40;</span>filename, <span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0066ff; font-weight:bold;">@lines</span> = <span style="color:#006666;">0</span>
    <span style="color:#0066ff; font-weight:bold;">@total_lines</span> = <span style="color:#996600;">`wc -l #{filename}`</span>.<span style="color:#9900CC;">to_i</span>
    record_progress<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    result = real_process<span style="color:#006600; font-weight:bold;">&#40;</span>filename, <span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    record_progress<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">100</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">unlink</span><span style="color:#006600; font-weight:bold;">&#40;</span>filename<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    result
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  protected
  <span style="color:#9966CC; font-weight:bold;">def</span> line_processed!
    <span style="color:#0066ff; font-weight:bold;">@lines</span> <span style="color:#006600; font-weight:bold;">+</span>= <span style="color:#006666;">1</span>
&nbsp;
    update<span style="color:#006600; font-weight:bold;">&#40;</span>@lines<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> update<span style="color:#006600; font-weight:bold;">&#40;</span>lines<span style="color:#006600; font-weight:bold;">&#41;</span>
    record_progress<span style="color:#006600; font-weight:bold;">&#40;</span>lines, <span style="color:#0066ff; font-weight:bold;">@total_lines</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Veamos un poco más en detalle algunas partes.</p>
<h3>Encolado</h3>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">enqueue</span><span style="color:#006600; font-weight:bold;">&#40;</span>file, <span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span>
    filename = <span style="color:#996600;">&quot;#{RAILS_ROOT}/tmp/#{self.name}-#{Time.now.to_i}&quot;</span>
    <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>filename, <span style="color:#996600;">&quot;wb&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span> f.<span style="color:#9900CC;">write</span><span style="color:#006600; font-weight:bold;">&#40;</span>file.<span style="color:#9900CC;">read</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
    Job.<span style="color:#9900CC;">enqueue</span>!<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">name</span>, :<span style="color:#996600;">'process'</span>, filename, <span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">id</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Este método es quien guarda en un lugar seguro el archivo. Utilizando el nombre de la clase actual (recuerden que este método está en una clase base, de donde luego vamos a heredar) y un timestamp por las dudas que se lleguen a hacer 2 uploads (cosa que en la práctica no pasa, pero por las dudas está).</p>
<p>Luego de guardar el archivo se encola el trabajo pasándole el archivo (el path completo) y cualquier otro argumento que se quiera.</p>
<p>Esto hará que luego el daemon de background instancia la clase &#8216;self.name&#8217; y llame al método process pasandole nuestros parámetros.</p>
<h3>Procesamiento</h3>
<p>El método genérico de procesamiento hace uso de un método que la clase base no tiene &#8216;real_process&#8217; que es el método que las clases hijas definarán para realizar el trabajo final :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#9966CC; font-weight:bold;">def</span> process<span style="color:#006600; font-weight:bold;">&#40;</span>filename, <span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0066ff; font-weight:bold;">@lines</span> = <span style="color:#006666;">0</span>
    <span style="color:#0066ff; font-weight:bold;">@total_lines</span> = <span style="color:#996600;">`wc -l #{filename}`</span>.<span style="color:#9900CC;">to_i</span>
    record_progress<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    result = real_process<span style="color:#006600; font-weight:bold;">&#40;</span>filename, <span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    record_progress<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">100</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">unlink</span><span style="color:#006600; font-weight:bold;">&#40;</span>filename<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    result
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>En este caso el método se encarga de saber cual es el total de lineas (de una manera tal vez no muy linda, pero que anda <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> ) y borrar el archivo al terminar el proceso.</p>
<h3>Un worker real</h3>
<p>Para que esto tenga sentido, debemos crear un worker que haga realmente algo, entonces por ejemplo podríamos tener un worker que sume puntos a los usuarios desde un archivo :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> UserPointProcessor <span style="color:#006600; font-weight:bold;">&lt;</span> FileWorker
  private
  <span style="color:#9966CC; font-weight:bold;">def</span> real_process<span style="color:#006600; font-weight:bold;">&#40;</span>file<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>.<span style="color:#9900CC;">transaction</span> <span style="color:#9966CC; font-weight:bold;">do</span>
      FasterCSV.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">read</span><span style="color:#006600; font-weight:bold;">&#40;</span>file<span style="color:#006600; font-weight:bold;">&#41;</span>, <span style="color:#ff3333; font-weight:bold;">:col_sep</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;<span style="color:#000099;">\t</span>&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>row<span style="color:#006600; font-weight:bold;">|</span>
         <span style="color:#008000; font-style:italic;"># Hacer algo con row</span>
&nbsp;
         line_processed!
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#996600;">&quot;Podemos retornar algun valor o status de exito&quot;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>De esta forma podemos ahora en algún controller hacer el encolado del trabajo :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#9966CC; font-weight:bold;">def</span> add_points
    <span style="color:#9966CC; font-weight:bold;">if</span> request.<span style="color:#9900CC;">post</span>?
      redirect_to admin_job_path<span style="color:#006600; font-weight:bold;">&#40;</span>UserPointProcessor.<span style="color:#9900CC;">enqueue</span><span style="color:#006600; font-weight:bold;">&#40;</span>params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:file</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">and</span> <span style="color:#0000FF; font-weight:bold;">return</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    render <span style="color:#996600;">'file_upload'</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>En este caso el template <code>file_upload</code> es un form con un <em>file field</em> para hacer el upload, sin ningún otro campo. La ruta <code>admin_job_path</code> nos la provee directamente <a href="http://github.com/ncr/background-fu">BackgroundFu</a>, generándonos también las vistas con AJAX para actualizar el estado, una linda barra de progreso que nos muestra el tiempo estimado para terminar entre otros datos útiles (o no tanto <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> ).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gazer.com.ar/2010/09/08/procesando-archivos-en-background-con-rails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Filtrando datos con jQuery</title>
		<link>http://www.gazer.com.ar/2010/06/25/filtrando-datos-con-jquery/</link>
		<comments>http://www.gazer.com.ar/2010/06/25/filtrando-datos-con-jquery/#comments</comments>
		<pubDate>Fri, 25 Jun 2010 03:19:21 +0000</pubDate>
		<dc:creator>Gazer</dc:creator>
				<category><![CDATA[Programación]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>

		<guid isPermaLink="false">http://www.gazer.com.ar/?p=1289</guid>
		<description><![CDATA[Filtrar elementos dentro de una lista o una tabla para realizar una búsqueda inline con jQuery es bastante simple, solo basta entender un poco donde va cada cosa. La función en cuestión que nos permite hacer esto es filter() que junto con un poco de trabajo para hacer un deep-search dentro del DOM nos da [...]]]></description>
			<content:encoded><![CDATA[<p>Filtrar elementos dentro de una lista o una tabla para realizar una búsqueda inline con jQuery es bastante simple, solo basta entender un poco donde va cada cosa. La función en cuestión que nos permite hacer esto es <a href="http://api.jquery.com/filter/">filter()</a> que junto con un poco de trabajo para hacer un deep-search dentro del DOM nos da esta funcionalidad.</p>
<p>Por ejemplo si queremos mostrar los elementos de una lista que coinciden con una búsqueda deberíamos hacer algo como :</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">  v <span style="color: #339933;">=</span> <span style="color: #3366CC;">'some word'</span><span style="color: #339933;">;</span>
  <span style="color: #009966; font-style: italic;">/* Ocultamos todos los LI */</span>
  $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#list ul li'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">hide</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009966; font-style: italic;">/* Filtramos y mostramos los que coinciden */</span>
  $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#list ul'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">contents</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">filter</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">return</span> innerSearch<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">,</span> v<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">show</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>La función innerSearch la pueden ver en el ejemplo, y básicamente hace un recorrido por el DOM y devolviendo true en aquellos tags donde su contenido de texto contiene el patrón buscado.</p>
<p>Eso nos da muchas posibilidades, ya que por ejemplo en lugar de un simple show se podría aplicar alguna clase CSS para resaltar, modificar el color o lo que se les pueda ocurrir.</p>
<p>Por razones de <em>performance</em> no es muy útil para un DOM muy complejo, pero para el <a href="http://club.speedy.com.ar/concursos/llevate-dos-entradas-para-el-avant-premiere-de-brigada-a/ganadores">caso</a> donde yo lo necesité funciona aceptablemente bien.</p>
<p>Dejo <a href='http://www.gazer.com.ar/wp-content/uploads/2010/06/jquery_filter.html' target="_blank">un ejemplo</a> completo con filtrado en listas y tablas.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gazer.com.ar/2010/06/25/filtrando-datos-con-jquery/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>HTML5 : Guardar el contenido de &lt;canvas&gt; en el servidor</title>
		<link>http://www.gazer.com.ar/2010/04/13/html5-guardar-el-contenido-de-canvas-en-el-servidor/</link>
		<comments>http://www.gazer.com.ar/2010/04/13/html5-guardar-el-contenido-de-canvas-en-el-servidor/#comments</comments>
		<pubDate>Tue, 13 Apr 2010 03:57:34 +0000</pubDate>
		<dc:creator>Gazer</dc:creator>
				<category><![CDATA[Programación]]></category>
		<category><![CDATA[canvas]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[Sinatra]]></category>

		<guid isPermaLink="false">http://www.gazer.com.ar/?p=1267</guid>
		<description><![CDATA[Hoy tenía ganas de hacer algo distinto (vamos, no quería trabajar ) así que me puse a jugar con HTML5, entre otras cosas con el tag &#60;canvas&#62; para poder dibujar. Luego de bajar varios ejemplos y tener un &#8216;paint&#8217; andando lo que quería era guardar la imagen, y llegué a este post donde el autor [...]]]></description>
			<content:encoded><![CDATA[<p>Hoy tenía ganas de hacer algo distinto (vamos, no quería trabajar <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> ) así que me puse a jugar con HTML5, entre otras cosas con el tag &lt;canvas&gt; para poder dibujar. Luego de bajar varios ejemplos y tener un &#8216;paint&#8217; andando lo que quería era guardar la imagen, y llegué a este <a href="http://www.nihilogic.dk/labs/canvas2image/">post</a> donde el autor deja guardar en PNG, JPG hasta incluso en BMP el contenido del canvas.</p>
<p>Pero que el usuario se pueda guardar la imagen no era mi idea, era más bien guardarle en el servidor. Por ejemplo para hacer una firma digital y usarla después en el sitio para firmar los posts como si fueran documentos <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> .</p>
<p>Al principio pensé que iba a ser <em>super</em> complicado, pero me encontré que todo fue mucho más fácil de lo que imaginé. Así que vamos por partes.</p>
<p>Vamos a empezar por el server. Como era muy poco código para este ejemplo, hice una aplicación en <a href="http://www.sinatrarb.com/">Sinatra</a> que me permite mostrar un canvas y luego hacer un POST con los datos. Es ideal en este caso, ya que el server queda de tan solo unas 20 líneas de código :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'sinatra'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'RMagick'</span>
&nbsp;
get <span style="color:#996600;">'/'</span> <span style="color:#9966CC; font-weight:bold;">do</span>
   erb <span style="color:#ff3333; font-weight:bold;">:index</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
post <span style="color:#996600;">'/'</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  <span style="color:#008000; font-style:italic;"># Ya completaremos ...</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Como se puede ver tenemos una vista en el root y el POST lo manejamos también en la raiz. Para procesar la imagen decidí usar la única gema que conozco, RMagick, que buscando en la documentación de ImageMagick me <a href="http://www.imagemagick.org/script/formats.php">encontré</a> con grata sorpresa que sale leer &#8216;Base64-encoded inline image&#8217; , que resulta que es justo el formato en que se obtienen los datos desde el canvas <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . La única diferencia es que hay que preceder el string con &#8216;inline:&#8217; y ya estamos, nuestro método POST queda así :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">post <span style="color:#996600;">'/'</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  data = <span style="color:#996600;">'inline:'</span> <span style="color:#006600; font-weight:bold;">+</span> request.<span style="color:#9900CC;">body</span>.<span style="color:#9900CC;">read</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">begin</span>
    image = <span style="color:#6666ff; font-weight:bold;">Magick::Image</span>.<span style="color:#9900CC;">read</span><span style="color:#006600; font-weight:bold;">&#40;</span>data<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">first</span>
&nbsp;
    image.<span style="color:#9900CC;">write</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'image.png'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#996600;">&quot;alert('Image saved successfully')&quot;</span>
  <span style="color:#9966CC; font-weight:bold;">rescue</span>
    <span style="color:#996600;">&quot;alert('Image format not recognized')&quot;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Habría que revisar la documentación y bugs de ImageMagick para ver que tipos de implicancia puede llegar a tener en la seguridad del sitio o del sistema, pero son cosas que no vienen al caso <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p>La vista (reducida para el ejemplo) puede resumirse en el siguiente HTML :</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">  &lt;canvas id=&quot;example&quot; width=&quot;200&quot; height=&quot;200&quot;&gt;
    This text is displayed if your browser does not support HTML5 Canvas.
  &lt;/canvas&gt;
&nbsp;
  &lt;input type=&quot;button&quot; id=&quot;submit&quot; value=&quot;Submit&quot; /&gt;</pre></div></div>

<p>Y un poco de javascript :</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;text/javascript&quot;</span><span style="color: #339933;">&gt;</span>
  $<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;input&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">click</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #006600; font-style: italic;">// jQuery todavía no habla bien con HTML5, hack para</span>
      <span style="color: #006600; font-style: italic;">// no usar un plugin.</span>
      <span style="color: #003366; font-weight: bold;">var</span> c <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#example&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      $.<span style="color: #660066;">post</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'/'</span><span style="color: #339933;">,</span> c.<span style="color: #660066;">toDataURL</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;script&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// Un dibujito estático para probar</span>
    <span style="color: #003366; font-weight: bold;">var</span> example <span style="color: #339933;">=</span> document.<span style="color: #660066;">getElementById</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'example'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #003366; font-weight: bold;">var</span> context <span style="color: #339933;">=</span> example.<span style="color: #660066;">getContext</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'2d'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    context.<span style="color: #660066;">fillStyle</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;rgb(255,0,0)&quot;</span><span style="color: #339933;">;</span>
    context.<span style="color: #660066;">fillRect</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">30</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">30</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">50</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">50</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
<span style="color: #339933;">&lt;/</span>script<span style="color: #339933;">&gt;</span></pre></div></div>

<p>Y ya estamos, al presionar el botón se envían los datos de la imagen dibujada, si está todo bien ImageMagick creará el archivo en el filesystem y por último devolverá algo de javascript para informar al usuario como salió todo. Obviamente si tuviéramos un sistema de usuarios en el server podríamos guardar la imagen para cada uno, pero de nuevo, no viene al caso.</p>
<p>El resultado final :</p>
<p><img src="http://www.gazer.com.ar/wp-content/uploads/2010/04/image.png" alt="" title="image" width="200" height="200" class="aligncenter size-full wp-image-1268" /></p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ identify <span style="color: #660033;">-verbose</span> image.png 
Image: image.png
  Format: PNG <span style="color: #7a0874; font-weight: bold;">&#40;</span>Portable Network Graphics<span style="color: #7a0874; font-weight: bold;">&#41;</span>
  Class: DirectClass
  Geometry: 200x200+<span style="color: #000000;">0</span>+<span style="color: #000000;">0</span>
  Resolution: 72x72
  Print <span style="color: #c20cb9; font-weight: bold;">size</span>: 2.77778x2.77778
  Colorspace: RGB
  Depth: <span style="color: #000000;">8</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">1</span>-bit
  Histogram:
     <span style="color: #000000;">37500</span>: <span style="color: #7a0874; font-weight: bold;">&#40;</span>  <span style="color: #000000;">0</span>,  <span style="color: #000000;">0</span>,  <span style="color: #000000;">0</span>,  <span style="color: #000000;">0</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #666666; font-style: italic;">#00000000 none</span>
      <span style="color: #000000;">2500</span>: <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">255</span>,  <span style="color: #000000;">0</span>,  <span style="color: #000000;">0</span>,<span style="color: #000000;">255</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #666666; font-style: italic;">#FF0000 red</span>
  Page geometry: 200x200+<span style="color: #000000;">0</span>+<span style="color: #000000;">0</span>
  Compression: Zip
  Properties:
    create-date: <span style="color: #000000;">2010</span>-04-13T00:<span style="color: #000000;">20</span>:<span style="color: #000000;">15</span>-03:00
    modify-date: <span style="color: #000000;">2010</span>-04-13T00:<span style="color: #000000;">20</span>:<span style="color: #000000;">15</span>-03:00
    signature: 0a42f3c85d6364e38f14dac554d26c62a90b84b06ac7f22264c9d964657ba8d6
  Tainted: False
  Filesize: 503b
  Number pixels: 39.1kb
  Version: ImageMagick 6.5.1-<span style="color: #000000;">0</span> <span style="color: #000000;">2009</span>-08-<span style="color: #000000;">27</span> Q16 OpenMP http:<span style="color: #000000; font-weight: bold;">//</span>www.imagemagick.org</pre></div></div>

<p>Probado en :</p>
<ul>
<li>Chromium 5.0.372.0 (44042) Ubuntu</li>
<li>Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.9) Gecko/20100401 Ubuntu/9.10 (karmic) Firefox/3.5.9</li>
</ul>
<p>Código completo : <a href='http://www.gazer.com.ar/wp-content/uploads/2010/04/html5_canvas_submit.zip'>html5_canvas_submit</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.gazer.com.ar/2010/04/13/html5-guardar-el-contenido-de-canvas-en-el-servidor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Casa y Casamiento</title>
		<link>http://www.gazer.com.ar/2010/04/09/casa-y-casamiento/</link>
		<comments>http://www.gazer.com.ar/2010/04/09/casa-y-casamiento/#comments</comments>
		<pubDate>Fri, 09 Apr 2010 04:59:41 +0000</pubDate>
		<dc:creator>Gazer</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Yo Estuve Ahí]]></category>

		<guid isPermaLink="false">http://www.gazer.com.ar/?p=1239</guid>
		<description><![CDATA[Y si, volví para seguir molestando con cosas que a nadie le interesa . En los últimos meses han pasado tantas cosas que ya ni encuentro un rato para sentarme a escribir . Para empezar me volví a mudar, si, si, 4 mudanzas en 4 meses, espero que esta vez sea la definitiva. Ahora, y [...]]]></description>
			<content:encoded><![CDATA[<p>Y si, volví para seguir molestando con cosas que a nadie le interesa <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . En los últimos meses han pasado tantas cosas que ya ni encuentro un rato para sentarme a escribir <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> .</p>
<p>Para empezar me <a href="http://www.gazer.com.ar/2010/01/13/ano-nuevo-vida-nueva/">volví</a> a mudar, si, si, 4 mudanzas en 4 meses, espero que esta vez sea la definitiva. Ahora, y después de 12 años, volví a mi Cipolletti &#8220;<em>natal</em>&#8220;, el que me vio hacer tantas cagadas de chico. Y más aún, volví al barrio donde viví toda mi secundaria (a menos de 100 mts de la casa donde vivíamos con mis viejos por esa época), toda una regresión <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p>Pero la cosa siguió y finalmente llegamos vivos al casamiento con mi (ex) novia y me tuve que disfrazar de &#8220;empresario&#8221; para aparentar un poco frente a la familia. Siempre es bueno dar una buena impresión, pero a mi me suele alcanzar con que sea buena o mala <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p style="text-align: center;"><a href="http://www.gazer.com.ar/wp-content/uploads/2010/04/c1.jpg"><img class="size-full wp-image-1241 alignnone" title="Empresariado" src="http://www.gazer.com.ar/wp-content/uploads/2010/04/c1.jpg" alt="" width="102" height="154" /> </a><a href="http://www.gazer.com.ar/wp-content/uploads/2010/04/c2.jpg"><img class="alignnone size-full wp-image-1242" title="c2" src="http://www.gazer.com.ar/wp-content/uploads/2010/04/c2.jpg" alt="" width="231" height="154" /> </a><a href="http://www.gazer.com.ar/wp-content/uploads/2010/04/c3.jpg"><img class="alignnone size-full wp-image-1243" title="c3" src="http://www.gazer.com.ar/wp-content/uploads/2010/04/c3.jpg" alt="" width="102" height="154" /></a></p>
<p>La fiesta fue, bueno, una fiesta, si me conocen saben como soy cuando hay joda, así que el resto se lo pueden imaginar. No faltó ni comida y mucho menos para tomar, barra libre, etc, etc &#8230; más de uno se fue gateando (yo volví manejando, para variar, en piloto automático). Cuando arrancó la joda, luego de que Nacho Morán (imitador/cantante de Choele Choel) hiciera su gracia, se armó alto bailongo, donde nadie se quedó sentado.</p>
<p style="text-align: center;"><a href="http://www.gazer.com.ar/wp-content/uploads/2010/04/c4.jpg"><img class="alignnone size-full wp-image-1244" title="Nacho Moran" src="http://www.gazer.com.ar/wp-content/uploads/2010/04/c4.jpg" alt="" width="231" height="154" /></a> <a href="http://www.gazer.com.ar/wp-content/uploads/2010/04/c5.jpg"><img class="alignnone size-full wp-image-1245" title="Plena Joda" src="http://www.gazer.com.ar/wp-content/uploads/2010/04/c5.jpg" alt="" width="231" height="154" /></a></p>
<p>Más entrada la noche una mesa dulce para cortar un poco el alcohol y si te agarra el control de alcoholemia poder mentir que fue por metabolizar los dulces <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> , aunque hay que se realista, en Cipollettia las 8AM no hay controles <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> .</p>
<p style="text-align: center;"><a href="http://www.gazer.com.ar/wp-content/uploads/2010/04/c6.jpg"><img class="alignnone size-full wp-image-1246" title="c6" src="http://www.gazer.com.ar/wp-content/uploads/2010/04/c6.jpg" alt="" width="217" height="144" /></a> <a href="http://www.gazer.com.ar/wp-content/uploads/2010/04/c7.jpg"><img class="alignnone size-full wp-image-1247" title="c7" src="http://www.gazer.com.ar/wp-content/uploads/2010/04/c7.jpg" alt="" width="217" height="144" /></a></p>
<p>Ya cuando los gallos empiezan a cantar empezamos a cerrar la joda con un foto de los valientes que duraron hasta el final.</p>
<p style="text-align: center;"><a href="http://www.gazer.com.ar/wp-content/uploads/2010/04/c8.jpg"><img class="alignnone size-full wp-image-1248" title="c8" src="http://www.gazer.com.ar/wp-content/uploads/2010/04/c8.jpg" alt="" width="217" height="144" /> </a><a href="http://www.gazer.com.ar/wp-content/uploads/2010/04/c9.jpg"><img class="alignnone size-full wp-image-1249" title="c9" src="http://www.gazer.com.ar/wp-content/uploads/2010/04/c9.jpg" alt="" width="217" height="144" /></a></p>
<p>Por último falta la luna de miel, que se da sobre fin de mes (nada de salir corriendo al otro día, hay que aprovechar las vacaciones <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> ).</p>
<p>Ah, y por si todo fue muy sutil y no se notó en las fotos anteriores, pegue &#8220;<em>altas llantas</em>&#8221; esa noche <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><a href="http://www.gazer.com.ar/wp-content/uploads/2010/04/c10.jpg"><img class="aligncenter size-full wp-image-1251" title="Altas llantas" src="http://www.gazer.com.ar/wp-content/uploads/2010/04/c10.jpg" alt="" width="266" height="400" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.gazer.com.ar/2010/04/09/casa-y-casamiento/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Apple iPad</title>
		<link>http://www.gazer.com.ar/2010/01/28/apple-ipad/</link>
		<comments>http://www.gazer.com.ar/2010/01/28/apple-ipad/#comments</comments>
		<pubDate>Thu, 28 Jan 2010 22:11:10 +0000</pubDate>
		<dc:creator>Gazer</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[ipad]]></category>
		<category><![CDATA[ipod]]></category>

		<guid isPermaLink="false">http://www.gazer.com.ar/?p=1233</guid>
		<description><![CDATA[Bueno, no voy a decir lo que ya todo el mundo ya debe haber leído (no multitask, es un iPod Touch grandote, solo con AT&#38;T bla bla bla) . www.youtube.com/watch?v=lQnT0zp8Ya4 Creo que eso resume más que bien lo que la mayoría de los no-fan de Apple piensan cuando leen la ficha técnica .]]></description>
			<content:encoded><![CDATA[<p>Bueno, no voy a decir lo que ya todo el mundo ya debe haber leído (no multitask, es un iPod Touch grandote, solo con AT&amp;T bla bla bla) <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p style="text-align: center;"><span class="youtube">
<object type="application/x-shockwave-flash" width="425" height="362" data="http://www.youtube.com/v/lQnT0zp8Ya4&amp;color1=3a3a3a&amp;color2=999999&amp;border=1&amp;fs=1&amp;hl=en&amp;autoplay=0&amp;showinfo=0&amp;iv_load_policy=3&amp;showsearch=0?rel=1">
<param name="movie" value="http://www.youtube.com/v/lQnT0zp8Ya4&amp;color1=3a3a3a&amp;color2=999999&amp;border=1&amp;fs=1&amp;hl=en&amp;autoplay=0&amp;showinfo=0&amp;iv_load_policy=3&amp;showsearch=0?rel=1" />
<param name="allowFullScreen" value="true" />
<param name="wmode" value="transparent" />
</object>
</span><p><a href="http://www.youtube.com/watch?v=lQnT0zp8Ya4"><img src="http://img.youtube.com/vi/lQnT0zp8Ya4/default.jpg" width="130" height="97" border=0></a></p><p><a href="http://www.youtube.com/watch?v=lQnT0zp8Ya4">www.youtube.com/watch?v=lQnT0zp8Ya4</a></p></p>
<p>Creo que eso resume más que bien lo que la mayoría de los no-fan de Apple piensan cuando leen la ficha técnica <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> .</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gazer.com.ar/2010/01/28/apple-ipad/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Migrando datos desde PHP a Rails</title>
		<link>http://www.gazer.com.ar/2010/01/22/migrando-datos-desde-php-a-rails/</link>
		<comments>http://www.gazer.com.ar/2010/01/22/migrando-datos-desde-php-a-rails/#comments</comments>
		<pubDate>Fri, 22 Jan 2010 20:02:41 +0000</pubDate>
		<dc:creator>Gazer</dc:creator>
				<category><![CDATA[Programación]]></category>
		<category><![CDATA[active record]]></category>
		<category><![CDATA[migracion]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.gazer.com.ar/?p=1227</guid>
		<description><![CDATA[Por esas cosas de la vida me encontré todo el día de hoy migrando datos viejos de un sistema hecho en PHP a uno hecho en Rails. Las cosas venían bastante simples definiendo modelos de ActiveRecord para las tablas de la base de datos vieja y reinsertando con modelos apuntando a las tablas nuevas. Pero [...]]]></description>
			<content:encoded><![CDATA[<p>Por esas cosas de la vida me encontré todo el día de hoy migrando datos viejos de un sistema hecho en PHP a uno hecho en Rails. Las cosas venían bastante simples definiendo modelos de ActiveRecord para las tablas de la base de datos vieja y reinsertando con modelos apuntando a las tablas nuevas. Pero &#8230; siempre hay un pero.</p>
<p>Resulta que el hermoso sistema anterior para evitar tener muchas tablas (o vaya a saber por qué) tenía en una parte un tabla donde cada field era un gran TEXT que contenía un array de PHP <a href="http://php.net/manual/en/function.serialize.php" target="_blank">serializado</a>.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> UserTextField <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  set_table_name <span style="color:#996600;">&quot;usertextfield&quot;</span>
  set_primary_key <span style="color:#996600;">&quot;userid&quot;</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> folders
    field3
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
$<span style="color:#006600; font-weight:bold;">&gt;</span> user = UserTextField.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">3</span><span style="color:#006600; font-weight:bold;">&#41;</span>
$<span style="color:#006600; font-weight:bold;">&gt;</span> user.<span style="color:#9900CC;">folders</span> <span style="color:#008000; font-style:italic;"># =&gt; 'a:2:{i:0;s:4:&quot;bkps&quot;;i:1;s:6:&quot;listas&quot;;'</span></pre></div></div>

<p>Justo cuando estaba por ponerme a parsear texto me encontré con <a href="http://github.com/jqr/php-serialize">php-serialize</a> que permite serializar y deserializar estos string en cómodos tipos nativos de Ruby.</p>
<p>El código final queda entonces algo como :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> UserTextField <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  set_table_name <span style="color:#996600;">&quot;usertextfield&quot;</span>
  set_primary_key <span style="color:#996600;">&quot;userid&quot;</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> folders
    PHP.<span style="color:#9900CC;">unserialize</span><span style="color:#006600; font-weight:bold;">&#40;</span>field3<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
$<span style="color:#006600; font-weight:bold;">&gt;</span> user = UserTextField.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">3</span><span style="color:#006600; font-weight:bold;">&#41;</span>
$<span style="color:#006600; font-weight:bold;">&gt;</span> user.<span style="color:#9900CC;">folders</span> <span style="color:#008000; font-style:italic;"># =&gt; [&quot;bkps&quot;, &quot;listas&quot;]</span></pre></div></div>

<p>Y la migración de datos pudo continuar sin problemas <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gazer.com.ar/2010/01/22/migrando-datos-desde-php-a-rails/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Audacity en Paranormal Activity</title>
		<link>http://www.gazer.com.ar/2010/01/14/audacity-en-paranormal-activity/</link>
		<comments>http://www.gazer.com.ar/2010/01/14/audacity-en-paranormal-activity/#comments</comments>
		<pubDate>Thu, 14 Jan 2010 18:46:10 +0000</pubDate>
		<dc:creator>Gazer</dc:creator>
				<category><![CDATA[Cine]]></category>
		<category><![CDATA[GNU+Linux]]></category>

		<guid isPermaLink="false">http://www.gazer.com.ar/?p=1220</guid>
		<description><![CDATA[La película es muy mala (no puedo creer que tenga casi 7 puntos en IMDB), pero mientras iba adelantandola a ver si pasaba algo me encontré que el protagonista usa Audacity para filtrar los ruidos de los &#8220;espíritus&#8221; : Ahora por lo menos se que con software libre puedo investigar los ruidos misteriosos de una [...]]]></description>
			<content:encoded><![CDATA[<p>La <a href="http://www.paranormalactivity-movie.com/">película</a> es muy mala (no puedo creer que tenga <a href="http://www.imdb.com/title/tt1179904/">casi 7 puntos en IMDB</a>), pero mientras iba adelantandola a ver si pasaba algo me encontré que el protagonista usa <a href="http://audacity.sourceforge.net/?lang=es">Audacity</a> para filtrar los ruidos de los &#8220;espíritus&#8221; :</p>
<p><a href="http://www.gazer.com.ar/wp-content/uploads/2010/01/Screenshot-PA.png"><img class="aligncenter size-full wp-image-1221" title="Screenshot-PA" src="http://www.gazer.com.ar/wp-content/uploads/2010/01/Screenshot-PA.png" alt="" width="491" height="267" /></a></p>
<p>Ahora por lo menos se que con software libre puedo investigar los ruidos misteriosos de una casa <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gazer.com.ar/2010/01/14/audacity-en-paranormal-activity/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Año Nuevo / Vida Nueva</title>
		<link>http://www.gazer.com.ar/2010/01/13/ano-nuevo-vida-nueva/</link>
		<comments>http://www.gazer.com.ar/2010/01/13/ano-nuevo-vida-nueva/#comments</comments>
		<pubDate>Wed, 13 Jan 2010 18:05:38 +0000</pubDate>
		<dc:creator>Gazer</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.gazer.com.ar/?p=1217</guid>
		<description><![CDATA[Hace un rato largo que no me siento a escribir, y principalmente es por lo tormentoso de estos dias. Nadie me obligo así que es con gusto, pero no obstante encontrar el tiempo para escribir algo que no interesa a nadie siempre es dificil . Este año arrancó con bastante revolucionado : me mudé de [...]]]></description>
			<content:encoded><![CDATA[<p>Hace un rato largo que no me siento a escribir, y principalmente es por lo tormentoso de estos dias. Nadie me obligo así que es con gusto, pero no obstante encontrar el tiempo para escribir algo que no interesa a nadie siempre es dificil <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p>Este año arrancó con bastante revolucionado : me mudé de ciudad, decidí casarme (técnicamente lo decidí el año pasado, pero oficialmente se lleva a cavo el corriente <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> ), <a href="http://twitpic.com/wwbev">compramos auto</a>, tenemos casa nueva, ya llevo 3 mudanzas en menos de 2 meses y no veo la hora desscansar el resto del año <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p>Feliz año (aunque ya empezó hace rato <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> ) para todos!.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gazer.com.ar/2010/01/13/ano-nuevo-vida-nueva/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Orquestando desde YouTube</title>
		<link>http://www.gazer.com.ar/2009/11/25/orquestando-desde-youtube/</link>
		<comments>http://www.gazer.com.ar/2009/11/25/orquestando-desde-youtube/#comments</comments>
		<pubDate>Wed, 25 Nov 2009 11:30:51 +0000</pubDate>
		<dc:creator>Gazer</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Música]]></category>

		<guid isPermaLink="false">http://www.gazer.com.ar/?p=1212</guid>
		<description><![CDATA[El otro día me pasaron este link desde donde podemos dirigir nuestra propiar orquesta con videos de youtube. Según el creador especificamente : In Bb 2.0 is a collaborative music and spoken word project conceived by Darren Solomon from Science for Girls, and developed with contributions from users. The videos can be played simultaneously &#8212; [...]]]></description>
			<content:encoded><![CDATA[<p>El otro día me pasaron <a href="http://www.inbflat.net/">este link</a> desde donde podemos dirigir nuestra propiar orquesta con videos de youtube. Según el creador especificamente :</p>
<p style="padding-left: 30px;"><span>In Bb 2.0</span> is a collaborative music and spoken word project conceived by <a href="http://www.scienceforgirls.net/bio.html" target="_blank">Darren Solomon</a> from <a href="http://www.scienceforgirls.net/" target="_blank">Science for Girls</a>, and developed with contributions from users.</p>
<p style="padding-left: 30px;">The videos can be played simultaneously &#8212; the soundtracks will work together, and the mix can be adjusted with the individual volume sliders.&#8221;</p>
<p>La verdad suena aceptablemente bien <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  aunque más de 10 videos en simultáneo ya se me complica.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gazer.com.ar/2009/11/25/orquestando-desde-youtube/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Implementación completa!!</title>
		<link>http://www.gazer.com.ar/2009/09/28/implementacion-completa/</link>
		<comments>http://www.gazer.com.ar/2009/09/28/implementacion-completa/#comments</comments>
		<pubDate>Tue, 29 Sep 2009 01:02:11 +0000</pubDate>
		<dc:creator>Gazer</dc:creator>
				<category><![CDATA[Tesis]]></category>

		<guid isPermaLink="false">http://www.gazer.com.ar/?p=1210</guid>
		<description><![CDATA[Finalmente terminé de programar la tesis, increíble!. Me llevó unas dos semanas solucionar el último problema que era poder acceder al registro EBP y al stack pointer para obtener el return value de un método, pero nada que 52 líneas de C no puedan solucionar , es un reverendo quilombo el JIT de mono, &#8220;sepanlón&#8221;. [...]]]></description>
			<content:encoded><![CDATA[<p>Finalmente terminé de programar la tesis, increíble!. Me llevó unas dos semanas solucionar el último problema que era poder acceder al registro EBP y al stack pointer para obtener el return value de un método, pero nada que 52 líneas de C no puedan solucionar <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> , es un reverendo quilombo el JIT de mono, &#8220;sepanlón&#8221;.</p>
<p>Ya desde hace unos días me puse a escribir el informe (motivado porque mi directora de tesis me retó porque todavía no había escrito nada <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> ) y hoy tuve una reunión para coordinar bien sobre en qué entrar en detalles.</p>
<p>Para fines de octubre espero ya poder tener el documento prácticametne terminado y el código &#8220;presentable&#8221; (también me retaron por no tener comentarios en el código <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> ).</p>
<p>La implementación final es una mezcla de C#, C y assembler que sorprende que interactúe sin caerse <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> . Las métricas finales no las tengo, pero las pruebas iniciales me gustan, y eso que hay varios lugares donde se puede optimizar.</p>
<p>En fin, un paso más hacia la liberación total de la &#8220;opresión&#8221; universitaria <img src='http://www.gazer.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gazer.com.ar/2009/09/28/implementacion-completa/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
