
<?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>Pebbl.es</title>
	<atom:link href="http://pebbl.es/feed/" rel="self" type="application/rss+xml" />
	<link>http://pebbl.es</link>
	<description>Software artesanal, desde 1997</description>
	<lastBuildDate>Mon, 07 May 2012 14:10:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>Comando bash util del día</title>
		<link>http://pebbl.es/2012/05/07/comando-bash-util-del-dia/</link>
		<comments>http://pebbl.es/2012/05/07/comando-bash-util-del-dia/#comments</comments>
		<pubDate>Mon, 07 May 2012 14:09:55 +0000</pubDate>
		<dc:creator>César</dc:creator>
				<category><![CDATA[Bash]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Sin categoría]]></category>

		<guid isPermaLink="false">http://pebbl.es/?p=214</guid>
		<description><![CDATA[Ejecuta el último comando, pero con sudo delante. Muy útil para todas las veces que se teclea un &#8220;churro&#8221; enorme y el sistema responde: &#8220;You don&#8217;t have permissions&#8230;&#8221;]]></description>
			<content:encoded><![CDATA[<pre class="brush: bash; title: ; notranslate">sudo !!</pre>
<p>Ejecuta el último comando, pero con sudo delante. Muy útil para todas las veces que se teclea un &#8220;churro&#8221; enorme y el sistema responde: &#8220;You don&#8217;t have permissions&#8230;&#8221;</p>
]]></content:encoded>
			<wfw:commentRss>http://pebbl.es/2012/05/07/comando-bash-util-del-dia/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Me encontraréis en BeCodeMyFriend</title>
		<link>http://pebbl.es/2012/04/26/me-encontrareis-en-becodemyfriend/</link>
		<comments>http://pebbl.es/2012/04/26/me-encontrareis-en-becodemyfriend/#comments</comments>
		<pubDate>Thu, 26 Apr 2012 13:19:04 +0000</pubDate>
		<dc:creator>César</dc:creator>
				<category><![CDATA[Proyectos]]></category>

		<guid isPermaLink="false">http://pebbl.es/?p=207</guid>
		<description><![CDATA[Desde hace ya casi un mes he unido fuerzas con BeCodeMyFriend, el colectivo Ágil de Valencia que desafía todas las definiciones. En &#8220;la madriguera&#8221; de BeCode comparten techo programadores ninjas, maestros ágiles, constructores de bicis y otros elementos variados. De hecho, ni siquiera compartimos techo ya que dos BeCodianos habituales trabajan en remoto desde Madrid. [...]]]></description>
			<content:encoded><![CDATA[<p>Desde hace ya casi un mes he unido fuerzas con <a href="http://www.becodemyfriend.com" target="_blank">BeCodeMyFriend</a>, el colectivo Ágil de Valencia que desafía todas las definiciones. En &#8220;la madriguera&#8221; de BeCode comparten techo programadores ninjas, maestros ágiles, constructores de bicis y otros elementos variados. De hecho, ni siquiera compartimos techo ya que dos BeCodianos habituales trabajan en remoto desde Madrid.</p>
<p>La lógica, si es que hay alguna, detrás de todo esto es crear un sitio donde se venga a trabajar y a jugar, a aprender y a enseñar y en definitiva a construir cosas. Para un soldado de fortuna como yo, es una manera de tener acceso a un equipo de expertos que me apoye en cualquier proyecto. Para el colectivo, se suma un colaborador en el que apoyarse para multiplicar fuerzas.</p>
<p><a href="http://www.becodemyfriend.com/2012/04/la-inauguracion-oficial-de-la-nueva-cueva/" target="_blank">Hoy inauguramos &#8220;la cueva&#8221; de BeCode</a>, el espacio que nos une. Si tenéis una oportunidad, no dudéis en pasar a saludar y tomar algo con nosotros.</p>
<p><a href="http://pebbl.es/wp-content/uploads/2012/04/IMG-20120425-WA0001.jpg"><img src="http://pebbl.es/wp-content/uploads/2012/04/IMG-20120425-WA0001.jpg" alt="" title="IMG-20120425-WA0001" width="400" height="533" class="aligncenter size-full wp-image-209" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://pebbl.es/2012/04/26/me-encontrareis-en-becodemyfriend/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Coding dojo en CSD, segundo intento</title>
		<link>http://pebbl.es/2012/03/26/coding-dojo-en-csd-segundo-intento/</link>
		<comments>http://pebbl.es/2012/03/26/coding-dojo-en-csd-segundo-intento/#comments</comments>
		<pubDate>Mon, 26 Mar 2012 12:02:40 +0000</pubDate>
		<dc:creator>César</dc:creator>
				<category><![CDATA[Programación]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://pebbl.es/?p=204</guid>
		<description><![CDATA[Esta mañana los BeCodianos me han llamado &#8220;el rey del if-then-else&#8221; por mi solución al Coding kata propuesto por CSD la semana pasada. ¿Ah si? La solución, refactorizada (en pastebin, para mayor legibilidad), y los tests. La mejoras: He dividido la clase Parseator en dos, creando una clase separada para el modelo de la gramática [...]]]></description>
			<content:encoded><![CDATA[<p>Esta mañana <a href="http://www.becodemyfriend.com/" target="_blank">los BeCodianos</a> me han llamado &#8220;el rey del if-then-else&#8221; por <a href="http://pebbl.es/2012/03/25/coding-dojo-en-csd/" title="Coding Dojo en CSD" target="_blank">mi solución al Coding kata propuesto por CSD</a> la semana pasada. ¿Ah si?</p>
<p><img src="http://pebbl.es/wp-content/uploads/2012/03/Challenge_accepted.jpg" alt="" title="Challenge_accepted" width="320" height="271" class="aligncenter size-full wp-image-205" /></p>
<p>La <a href="http://pastebin.com/aTa0zkae" target="_blank">solución</a>, refactorizada (en pastebin, para mayor legibilidad), y <a href="http://pastebin.com/yF6CPT9H" target="_blank">los tests</a>.</p>
<p>La mejoras: </p>
<ul>
<li>He dividido la clase Parseator en dos, creando una clase separada para el modelo de la gramática a parsear, y otro para el parseador en si.</li>
<li>He usado atajos de Ruby y construcciones tipo case para simplificar (o no) el código.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://pebbl.es/2012/03/26/coding-dojo-en-csd-segundo-intento/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Coding Dojo en CSD</title>
		<link>http://pebbl.es/2012/03/25/coding-dojo-en-csd/</link>
		<comments>http://pebbl.es/2012/03/25/coding-dojo-en-csd/#comments</comments>
		<pubDate>Sun, 25 Mar 2012 11:52:29 +0000</pubDate>
		<dc:creator>César</dc:creator>
				<category><![CDATA[Programación]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://pebbl.es/?p=201</guid>
		<description><![CDATA[La semana pasada me pasé por el segundo coding dojo en CSD, para conocer a otros desarrolladores y estirar los músculos de programar. La kata en si no era muy compleja (enunciado en PDF), pero el truco estaba en que había que programarla usando técnicas de TDD. Interesante, puesto que una de las desventajas del [...]]]></description>
			<content:encoded><![CDATA[<p>La semana pasada me pasé por el <a href="http://csd.com.es/csd-celebra-su-ii-coding-dojo/" target="_blank">segundo coding dojo en CSD</a>, para conocer a otros desarrolladores y estirar los músculos de programar. </p>
<p>La kata en si no era muy compleja (<a href="http://www.csd.com.es/wp-content/uploads/2012/03/INSTRUCCIONES-II-CODING-DOJO-EN-CSD.pdf" target="_blank">enunciado en PDF</a>), pero el truco estaba en que había que programarla usando técnicas de <a href="http://es.wikipedia.org/wiki/Test-driven_development" target="_blank">TDD</a>. Interesante, puesto que una de las desventajas del TDD es que la velocidad inicial de desarrollo es bastante baja.</p>
<p>Para desarrollar la kata nos emparejaron e hicimos <a href="http://es.wikipedia.org/wiki/T%C3%A9cnica_Pomodoro" target="_blank">dos pomodoros</a> de desarrollo con cinco minutos de descanso para discutir en grupo por dónde íbamos.</p>
<p><strong>Resumen de la kata</strong></p>
<p>La kata en si consistía en desarrollar un intérprete de líneas de comando al que se le pasan flags de tres tipos:</p>
<ul>
<li>-l: Flag booleano</li>
<li>-p 8080: Flag numérico</li>
<li>-d /tmp/log: Flag de texto</li>
</ul>
<p>El primer paso es desarrollar un esquema en el que se indiquen los flags que acepta el programa, de qué tipo son y el valor por defecto si se omite el flag. Una vez tenemos el esquema, el programa tiene que ser capaz de interpretar una cadena de entrada, analizar si es sintácticamente correcta, analizar si es semánticamente correcta y lanzar excepciones si la entrada no es correcta.</p>
<p><strong>Finalmente&#8230; antes de enseñaos la solución</strong></p>
<p>Desde aquí, gracias a la gente de CSD por organizar el Dojo en las mazmorras de su oficina y por echarnos de comer y beber (free beer!) mientras programábamos. <img src='http://pebbl.es/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><strong>Nuestra solución</strong></p>
<p>Aunque no conseguimos resolver la kata en dos pomodoros, aquí estos son los tests y la solución en Ruby que creamos mi compañero Yago y yo.</p>
<p>Los tests:</p>
<pre class="brush: ruby; title: ; notranslate">
require_relative '../lib/parseator.rb'

describe Parseator do
  before :each do
    @example_in = {&quot;l&quot; =&gt; [&quot;bool&quot;, false],
                           &quot;p&quot; =&gt; [&quot;number&quot;, 8080],
                           &quot;d&quot; =&gt; [&quot;string&quot;, &quot;/usr/local&quot;] }
    @parser = Parseator.new(@example_in)
  end
  describe &quot;, Sintactic Tests&quot; do
    it &quot;instantiates a Parseator object&quot; do
     @parser.should be_an_instance_of Parseator
    end
    it &quot;parses the empty string as valid&quot; do
      @parser.valid?(&quot;&quot;).should ==  true
    end
    it &quot;fails if first flag does not start with -&quot; do
      @parser.valid?(&quot;poop&quot;).should ==  false
    end
    it &quot;parses a single boolean flag&quot; do
      @parser.valid?(&quot;-t&quot;).should ==  true
    end
    it &quot;parses N boolean flags&quot; do
      @parser.valid?(&quot;-p -m&quot;).should == true
    end
    it &quot;parses a single flag with args&quot; do
      @parser.valid?(&quot;-p 8080&quot;).should == true
    end
    it &quot;parses a mix of boolean and arg flags without negative numbers&quot; do
      @parser.valid?(&quot;-p 8080 -m -l /hola/yo&quot;).should == true
    end
    it &quot;parses a mix of boolean and arg flags without negative numbers with traling and leading spaces&quot; do
      @parser.valid?(&quot;-p 8080 -m -l /hola/yo&quot;).should == true
    end
    it &quot;fails with an incorrect mix of boolean and arg flags with negative numbers&quot; do
      @parser.valid?(&quot;-p 8080 -m -500 p -l /hola/yo&quot;).should == false
    end
    it &quot;parses a mix of boolean and arg flags with negative numbers&quot; do
      @parser.valid?(&quot;-p 8080 -m -500 -l /hola/yo&quot;).should == true
    end
    it &quot;parses a mix of boolean and arg flags with negative numbers without spaces before argument&quot; do
      @parser.valid?(&quot;-p8080 -m -500 -l /hola/yo&quot;).should == true
    end
  end

  describe &quot;, Semantic Tests, &quot; do
    it &quot;raises exception when passing a flag that is not defined&quot; do
      lambda { @parser.parse(&quot;-t&quot;) }.should raise_error UndefinedParam
    end
    it &quot;returns a hash with default value when passing a single boolean flag&quot; do
      test_string = &quot;-l&quot;
      @parser.parse(test_string).should have_key(&quot;l&quot;)
      @parser.parse(test_string)[&quot;l&quot;].should == true
    end
    it &quot;returns a hash with false when passing an empty string, for the boolean flag&quot; do
      @parser.parse(&quot;&quot;).should have_key(&quot;l&quot;)
      @parser.parse(&quot;&quot;)[&quot;l&quot;].should == false
    end
    it &quot;returns a hash with value when passing a single string&quot; do
      test_string = &quot;-d /usr/bin&quot;
      @parser.parse(test_string).should have_key(&quot;d&quot;)
      @parser.parse(test_string)[&quot;d&quot;].should == &quot;/usr/bin&quot;
    end
    it &quot;returns a hash with value when passing a single number&quot; do
      test_string = &quot;-p 8080&quot;
      @parser.parse(test_string).should have_key(&quot;p&quot;)
      @parser.parse(test_string)[&quot;p&quot;].should == 8080
    end
    it &quot;returns a hash with value when passing a single negative number&quot; do
      test_string = &quot;-p -8080&quot;
      @parser.parse(test_string).should have_key(&quot;p&quot;)
      @parser.parse(test_string)[&quot;p&quot;].should == -8080
    end
    it &quot;returns correctly when passing mix of strings, booleans and numbers&quot; do
      test_string = &quot;-p -8080 -l -d /usr/test&quot;
      @parser.parse(test_string).should have_key(&quot;p&quot;)
      @parser.parse(test_string)[&quot;p&quot;].should == -8080
      @parser.parse(test_string).should have_key(&quot;d&quot;)
      @parser.parse(test_string)[&quot;d&quot;].should == &quot;/usr/test&quot;
      @parser.parse(test_string).should have_key(&quot;l&quot;)
      @parser.parse(test_string)[&quot;l&quot;].should == true
    end
    it &quot;defaults correctly with some params defined&quot; do
      test_string = &quot;-p -8080 -d /usr/test&quot;
      @parser.parse(test_string).should have_key(&quot;l&quot;)
      @parser.parse(&quot;&quot;)[&quot;l&quot;].should == false
    end
    it &quot;defaults correctly with no params defined, aka empty string test&quot; do
      test_string = &quot;-p -8080 -d /usr/test&quot;
      @parser.parse(test_string).should have_key(&quot;l&quot;)
      @parser.parse(&quot;&quot;)[&quot;l&quot;].should == false
    end
    it &quot;fails when passing valid and invalid flags&quot; do
      test_string = &quot;-p -8080 -m /usr/test&quot;
      lambda { @parser.parse(test_string) }.should raise_error UndefinedParam
    end
    it &quot;raises exception, with explanation test when passing a flag that is not defined&quot; do
      lambda { @parser.parse(&quot;-t&quot;) }.should raise_error UndefinedParam, &quot;Syntax error. Correct format is UNIMPLEMENTED&quot;
    end
    it &quot;raises exception, with explanation, passing a defined flag with wrong param&quot; do
      lambda { @parser.parse(&quot;-l /usr/test&quot;) }.should raise_error IncorrectParam, &quot;Incorrect parameter -l /usr/test&quot;
    end
    it &quot;raises exception, with explanation, passing a number flag to a string flag&quot; do
      lambda { @parser.parse(&quot;-d 8080&quot;) }.should raise_error IncorrectParam, &quot;Incorrect parameter -d 8080&quot;
    end
    it &quot;raises exception, with explanation, passing a number flag with wrong param&quot; do
      lambda { @parser.parse(&quot;-p /usr/test&quot;) }.should raise_error IncorrectParam, &quot;Incorrect parameter -p /usr/test&quot;
    end
  end
end
</pre>
<p>El código:</p>
<pre class="brush: ruby; title: ; notranslate">
class UndefinedParam &lt; StandardError; end
class IncorrectSyntax &lt; StandardError; end
class IncorrectParam &lt; StandardError; end

# Extend class string to check if params are numbers (floats included)
class String
  def is_numeric?
    begin Float(self) ; true end rescue false
  end
end

class Parseator
  # Constructor takes as parameter a hash with the valid flags, type and default value
  def initialize(model_hash)
    @model = model_hash
  end

  # valid? returns true if params is syntactically correct
  def valid?(params)
    if params == &quot;&quot;
      return true
    else
      if params =~ /^\s*(\-[a-zA-Z]{1}\s*(\-?[0-9]+|[^-\s]+)*\s*)*\s*$/
        return true
      else
        return false
      end
    end
  end

  # returns a Hash with the parameters and the set values
  # or raises an exception if there are Syntax or Semantic errors
  def parse(params)
    params_out = Hash.new
    if valid?(params) # First, check there are no syntax errors
      # first go through the input string and add that to the results
      # match[0] is the flag
      # match[1] is the value
      params.scan(/\-([a-zA-Z]{1})\s*(\-?[0-9]+|[^-\s]+)*/).each do |match|
        if @model.has_key?(match[0])
          # bool params
          if @model[match[0]][0] == &quot;bool&quot;
            unless match[1].nil? # bool types do not have a value
              raise IncorrectParam, &quot;Incorrect parameter -#{match[0]} #{match[1]}&quot;
            end
            params_out[match[0]] = true
          # string params
          elsif @model[match[0]][0] == &quot;string&quot;
            if match[1].nil? || match[1].is_numeric?
              raise IncorrectParam, &quot;Incorrect parameter -#{match[0]} #{match[1]}&quot;
            end
            params_out[match[0]] = match[1]
          # number params
          elsif @model[match[0]][0] == &quot;number&quot;
            if match[1].nil? || !match[1].is_numeric?
              raise IncorrectParam, &quot;Incorrect parameter -#{match[0]} #{match[1]}&quot;
            end
            params_out[match[0]] = match[1].to_i
          end
        else
          raise UndefinedParam, &quot;Syntax error. Correct format is UNIMPLEMENTED&quot;
        end
      end

      # second, go through the model and see what params are missing, to add the defaults
      @model.keys.each do |key|
        unless params_out.has_key?(key)
          params_out[key] = @model[key][1] # default value
        end
      end
      return params_out
    else # Raise syntax error if not valid?
      # This method can be refined to analyze the string for the location of the syntax error(s)
      # Left as an exercise for the reader
      raise IncorrectSyntax
    end
  end
end
</pre>
<p>Ahora que lo miro&#8230; @model huele a refactoring&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://pebbl.es/2012/03/25/coding-dojo-en-csd/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Instalar un entorno de desarrollo Ruby on Rails en OS X 10.7.3</title>
		<link>http://pebbl.es/2012/02/24/instalar-un-entorno-de-desarrollo-ruby-on-rails-en-os-x-10-7-3/</link>
		<comments>http://pebbl.es/2012/02/24/instalar-un-entorno-de-desarrollo-ruby-on-rails-en-os-x-10-7-3/#comments</comments>
		<pubDate>Fri, 24 Feb 2012 16:10:18 +0000</pubDate>
		<dc:creator>César</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://pebbl.es/?p=190</guid>
		<description><![CDATA[Después de varios intentos frustrados, usando dos y hasta tres tutoriales diferentes, he conseguido instalar mi entorno de desarrollo RoR en OS X 10.7.3. No es tarea fácil, pero en menos de una hora lo tendréis listo si seguís los mismos pasos que yo. Aparte, os recomiendo que instaléis también RVM para la gestión de [...]]]></description>
			<content:encoded><![CDATA[<p>Después de varios intentos frustrados, usando dos y hasta tres tutoriales diferentes, he conseguido instalar mi entorno de desarrollo RoR en OS X 10.7.3. No es tarea fácil, pero en menos de una hora lo tendréis listo si seguís los mismos pasos que yo.</p>
<p>Aparte, os recomiendo que instaléis también RVM para la gestión de diferentes versiones de Ruby y Rails, que luego os simplificará la vida cuando tengáis que cambiar el entorno de desarrollo para mantener aplicaciones que ya tengáis en el servidor.</p>
<p>Finalmente también os recomiendo Passenger para simplificar la integración con Apache y así emular lo más posible el entorno de producción, en lugar de usar WEBrick el servidor web que lleva Rails por defecto.</p>
<p>Mi configuración:</p>
<ul>
<li>Mac OSX 10.7.3</li>
<li>XCode 4.3</li>
<li>RVM 1.10.3</li>
<li>Ruby 1.9.3</li>
<li>Rails 3.2.1</li>
<li>MySQL 5.5</li>
<li>Passenger 3.0.11</li>
</ul>
<p>Ten en cuenta que muchos de los comandos instalarán las últimas versiones de las herramientas y librerías, así que tus resultados puede variar. Por ejemplo, al ejecutar &#8216;gem install rails&#8217; en el momento de publicar este post, la versión que se instala es Rails 3.2.1., la última versión disponible a finales de Febrero 2012.</p>
<h1>1. Instalar Xcode</h1>
<p>Te lo puedes bajar en el App Store de Apple, o en el <a href="https://developer.apple.com/downloads/index.action" target="_blank">Developer center</a>. Necesitas un Apple ID.</p>
<p>Con XCode 4.3 las herramientas de la línea de comando son opcionales. Instálalas en Xcode > Preferences > Downloads.</p>
<h1>2. Homebrew</h1>
<p><a href="http://mxcl.github.com/homebrew/" target="_blank">Homebrew</a> es una applicación que nos sirve para facilitar la instalación de software libre sobre Mac OS X. <a href="https://github.com/mxcl/homebrew/wiki/installation" target="_blank">Siguiendo las instrucciones</a>: </p>
<pre class="brush: plain; title: ; notranslate">$&gt; /usr/bin/ruby -e &quot;$(curl -fsSL https://raw.github.com/gist/323731)&quot;
==&gt; This script will install:
/usr/local/bin/brew
/usr/local/Library/Formula/...
/usr/local/Library/Homebrew/...

Press enter to continue
==&gt; Downloading and Installing Homebrew...
==&gt; Installation successful!
Now type: brew help
</pre>
<h1>3. RVM</h1>
<p>Para instalar RVM, el sistema de gestión (que no control) de versiones de Ruby, lo primero es instalar Git (este si que es un sistema de control de versiones, para liarlo más)</p>
<pre class="brush: plain; title: ; notranslate">$&gt; brew install git</pre>
<p>Una vez tenemos git instalado, instalamos RVM&#8230;</p>
<pre class="brush: plain; title: ; notranslate">
$&gt; bash -s stable &lt; &lt;(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer)
1

... y lo configuramos:
1
$&gt; source ~/.rvm/scripts/rvm
</pre>
<p>Pero no todo es tan fácil. Si ejecutamos</p>
<pre class="brush: plain; title: ; notranslate">
$&gt; rvm notes

Notes for Mac OS X 10.7.3, No Xcode.

For JRuby:  Install the JDK. See http://developer.apple.com/java/download/  # Current Java version &quot;1.6.0_26&quot;
For IronRuby: Install Mono &gt;= 2.6
For Ruby 1.9.3: Install libksba # If using Homebrew, 'brew install libksba'
...
</pre>
<p>Es decir, que si queremos soporte para Ruby 1.9.3 tenemos que instalar libksba:</p>
<pre class="brush: plain; title: ; notranslate">
brew install libksba
</pre>
<p>Y luego instalar RVM con clang como compilador (gracias <a href="http://stackoverflow.com/questions/8032824/cant-install-ruby-under-lion-with-rvm-gcc-issues" target="_blank">Stack Overflow</a>)</p>
<pre class="brush: plain; title: ; notranslate">
$&gt; rvm install 1.9.3 --with-gcc=clang
</pre>
<p>Para hacer que 1.9.3 sea la versión por defecto:</p>
<pre class="brush: plain; title: ; notranslate">
$&gt; rvm --default use 1.9.3
$&gt; ruby -v
$&gt; ruby 1.9.3p125 (2012-02-16 revision 34643) [x86_64-darwin11.3.0]
</pre>
<h1>4. Rails</h1>
<p>A medida que vamos instalando herramientas, se hace más fácil la instalación:</p>
<pre class="brush: plain; title: ; notranslate">
$&gt; gem install rails
</pre>
<p>Esto instala Rails y gems dependientes, incluyendo Bundler (gestión de gemas para deployment). Comprobemos que versión tenemos instalada.</p>
<pre class="brush: plain; title: ; notranslate">
$&gt; rails --version
Rails 3.2.1
</pre>
<h1>5. MySQL 5.5</h1>
<p>Puedes elegir la base de datos SQL o No-SQL que más te guste. Para esta guía he elegido MySQL 5.5.</p>
<pre class="brush: plain; title: ; notranslate">
$&gt; brew install mysql
</pre>
<p>Para crear la base de datos y los usuarios:</p>
<pre class="brush: plain; title: ; notranslate">
$&gt; unset TMPDIR
$&gt; mysql_install_db --verbose --user=`whoami` --basedir=&quot;$(brew --prefix mysql)&quot; --datadir=/usr/local/var/mysql --tmpdir=/tmp
</pre>
<p>Lanza el servidor</p>
<pre class="brush: plain; title: ; notranslate">
$&gt; mysql.server start
</pre>
<p>Haz tu instalación de MySQL más segura (cambia el password de root, borra los usuarios anónimos, bloquea el acceso remoto, borra la base de datos de test y vuelve a cargar las tablas de privilegios):</p>
<pre class="brush: plain; title: ; notranslate">
$&gt; mysql_secure_installation
</pre>
<p>Crear un usuario de desarrollo de MySQL</p>
<pre class="brush: plain; title: ; notranslate">
$&gt; mysql -u root -p
mysql&gt; use mysql;
mysql&gt; insert into user(host, user, password) values ('localhost', 'dev_user', '');
</pre>
<h1>6. Passenger</h1>
<p>Phusion passenger es un módulo de Apache para deployear (¿alguien conoce un verbo mejor?) aplicaciones de Ruby on Rails. Es el método recomendado por los creadores de Rails.</p>
<pre class="brush: plain; title: ; notranslate">
$&gt; gem install passenger
$&gt; passenger-install-apache2-module
</pre>
<p>Para configurar Apache con passenger, sigue las instrucciones en pantalla (te las resumo a continuación). Enciende Apache desde System Preferences > Sharing > Web Sharing (tiene que estar activado)</p>
<p><a href="http://pebbl.es/wp-content/uploads/2012/02/Screen-Shot-2012-02-23-at-6.01.13-PM.png"><img src="http://pebbl.es/wp-content/uploads/2012/02/Screen-Shot-2012-02-23-at-6.01.13-PM-300x253.png" alt="" title="Screen Shot 2012-02-23 at 6.01.13 PM" width="300" height="253" class="aligncenter size-medium wp-image-193" /></a></p>
<p>Edita con sudo el fichero /etc/apache2/httpd.conf e incluye la configuración de Passenger al final del fichero:</p>
<pre class="brush: plain; title: ; notranslate">
Include /etc/apache2/other/passenger.conf
</pre>
<p>Cierra httpd.conf y crea el fichero de configuración para passenger</p>
<pre class="brush: plain; title: ; notranslate">
touch /etc/apache2/other/passenger.conf
</pre>
<p>Edita con sudo el fichero /etc/apache2/passenger.conf</p>
<pre class="brush: plain; title: ; notranslate">
LoadModule passenger_module /Users/cesar/.rvm/gems/ruby-1.9.3-p125/gems/passenger-3.0.11/ext/apache2/mod_passenger.so
PassengerRoot /Users/cesar/.rvm/gems/ruby-1.9.3-p125/gems/passenger-3.0.11
PassengerRuby /Users/cesar/.rvm/wrappers/ruby-1.9.3-p125/ruby
</pre>
<p><strong>Ten en cuenta que mi directorio home es 'cesar', pero el tuyo seguramente será otro.</strong></p>
<p>Reinicia Apache</p>
<pre class="brush: plain; title: ; notranslate">
sudo apachectl restart
</pre>
<p>Comprueba en /var/log/apache2/error_log que no hay errores. Por ejemplo:</p>
<pre class="brush: plain; title: ; notranslate">
[Thu Feb 23 18:00:21 2012] [notice] Apache/2.2.21 (Unix) DAV/2 Phusion_Passenger/3.0.11 configured -- resuming normal operations
</pre>
<h1>7. Crea una aplicación Rails de ejemplo</h1>
<p>Voy a seguir el ejemplo típico del blog de Rails, que está en la guía <a href="http://guides.rubyonrails.org/getting_started.html#creating-a-new-rails-project" target="_blank">Getting Started with Rails</a>.</p>
<p>Crear el directorio para los proyectos rails. Yo lo tengo en mi home:</p>
<pre class="brush: plain; title: ; notranslate">
$&gt; cd ~
$&gt; mkdir railsprojects
$&gt; cd railsprojects
</pre>
<p>Para crear la aplicación:</p>
<pre class="brush: plain; title: ; notranslate">
$&gt; rails new blog
</pre>
<p>Configura Passenger y Apache para esta aplicación, activando virtual hosts si no está activado en /etc/apache2/httpd.conf . Busca:</p>
<pre class="brush: plain; title: ; notranslate">
# Virtual hosts
# Include /private/etc/apache2/extra/httpd-vhosts.conf
</pre>
<p>Borra el '#' de la segunda línea, para incluir el fichero de hosts virtuales. A continuación, edita (con sudo) /private/etc/apache2/extra/httpd-vhosts.conf y añade:</p>
<pre class="brush: plain; title: ; notranslate">
&lt;VirtualHost *:80&gt;
       ServerName blog.lvh.me
       DocumentRoot /Users/cesar/railsprojects/blog/public
       RailsEnv development
       &lt;Directory /Users/cesar/railsprojects/blog/public&gt;
           AllowOverride all
           Order allow,deny
           Allow from all
           Options -Indexes +FollowSymLinks MultiViews
       &lt;/Directory&gt;
&lt;/VirtualHost&gt;
</pre>
<p><strong>Ten en cuenta que mi directorio home es 'cesar', pero el tuyo puede ser otro.</strong></p>
<p>Reinicia Apache una vez más con sudo apachectl restart</p>
<p>En tu navegador visita blog.lvh.me (ya he <a href="http://pebbl.es/2012/01/03/local-virtual-hosts-y-lvh-me/" title="Local virtual hosts y lvh.me" target="_blank">hablado de LVH</a> en otro post. Es lo mismo que localhost).</p>
<p><a href="http://pebbl.es/wp-content/uploads/2012/02/Screen-Shot-2012-02-23-at-7.14.09-PM.png"><img src="http://pebbl.es/wp-content/uploads/2012/02/Screen-Shot-2012-02-23-at-7.14.09-PM-300x231.png" alt="" title="Screen Shot 2012-02-23 at 7.14.09 PM" width="300" height="231" class="aligncenter size-medium wp-image-194" /></a></p>
<p>Si ves esta pantalla, ya tienes Rails configurado y funcionando. Ahora hay que terminar de cerrar el stack, configurando la base de datos MySQL.</p>
<p>Editar el Gemfile en el directorio blog y añade:</p>
<pre class="brush: plain; title: ; notranslate">gem 'mysql2'</pre>
<p>Instala la nueva gema con</p>
<pre class="brush: plain; title: ; notranslate">
$&gt; Bundle install
</pre>
<p>Edita ~/railsprojects/blog/config/database.yml y cambia la sección 'development':</p>
<p>development:<br />
  adapter: mysql2<br />
  encoding: utf8<br />
  database: blog_development<br />
  pool: 5<br />
  username: dev_user<br />
  password:<br />
  socket: /tmp/mysql.sock</p>
<p>Crea la base de datos:</p>
<pre class="brush: plain; title: ; notranslate">
$&gt; rake db:create
</pre>
<p>Dale permisos al usuario dev_user:</p>
<pre class="brush: plain; title: ; notranslate">
$&gt; mysql -u root -p
mysql&gt; grant SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD on *.* to 'dev_user'@'localhost';
$&gt; flush privileges;
</pre>
<p>Genera el scaffolding de Post, que crea una migración con el script en SQL para modificar la base de datos:</p>
<pre class="brush: plain; title: ; notranslate">
$&gt; rails generate scaffold Post name:string title:string content:text
</pre>
<p>Si se ha creado una tabla posts en la base de datos: Has triunfado. Enhorabuena ya tienes el entorno de Rails listo en tu Mac OS X 10.7.3</p>
]]></content:encoded>
			<wfw:commentRss>http://pebbl.es/2012/02/24/instalar-un-entorno-de-desarrollo-ruby-on-rails-en-os-x-10-7-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Este jueves, presentando Bisicalc en Betabeers</title>
		<link>http://pebbl.es/2012/01/30/este-jueves-presentando-bisicalc-en-betabeers/</link>
		<comments>http://pebbl.es/2012/01/30/este-jueves-presentando-bisicalc-en-betabeers/#comments</comments>
		<pubDate>Mon, 30 Jan 2012 18:48:52 +0000</pubDate>
		<dc:creator>César</dc:creator>
				<category><![CDATA[Bisicalc]]></category>

		<guid isPermaLink="false">http://pebbl.es/?p=186</guid>
		<description><![CDATA[Este jueves 2 de Febrero voy a hacer una presentación cortita sobre Bisicalc en el Betabeers Valencia. Si tenéis curiosidad por conocer la base técnica de la web, os podeis pasar el jueves 2: 20:30h Parc Cientific de la Universitat de Valencia Catedrático Agustín Escardino 9 Valencia]]></description>
			<content:encoded><![CDATA[<p>Este jueves 2 de Febrero voy a hacer una presentación cortita sobre Bisicalc en el <a href="http://dir.betabeers.com/event/36/show" target="_blank">Betabeers Valencia</a>.</p>
<p>Si tenéis curiosidad por conocer la base técnica de la web, os podeis pasar el jueves 2:</p>
<p>20:30h<br />
Parc Cientific de la Universitat de Valencia<br />
Catedrático Agustín Escardino 9<br />
Valencia</p>
]]></content:encoded>
			<wfw:commentRss>http://pebbl.es/2012/01/30/este-jueves-presentando-bisicalc-en-betabeers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Usar subconsultas (subqueries) con mysqldump</title>
		<link>http://pebbl.es/2012/01/23/usar-subconsultas-subqueries-con-mysqldump/</link>
		<comments>http://pebbl.es/2012/01/23/usar-subconsultas-subqueries-con-mysqldump/#comments</comments>
		<pubDate>Mon, 23 Jan 2012 16:15:34 +0000</pubDate>
		<dc:creator>César</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://pebbl.es/?p=180</guid>
		<description><![CDATA[Para estudiar una porción de los datos de Bisicalc, necesitaba poner en un fichero .sql el resultado de una consulta: El problema es que al usar mysqldump me daba un error: Table &#8216;updates&#8217; was not locked with LOCK TABLES (1100) La solución: llamar a mysqldump con el parámetro &#8220;&#8211;lock-all-tables&#8221;]]></description>
			<content:encoded><![CDATA[<p>Para estudiar una porción de los datos de Bisicalc, necesitaba poner en un fichero .sql el resultado de una consulta:</p>
<pre class="brush: sql; title: ; notranslate">
SELECT *
FROM `statuses`
WHERE update_id in (
   select id
   from updates
   where timestamp &gt;='2011-12-01' and timestamp &lt; '2012-01-01'
)
</pre>
<p>El problema es que al usar mysqldump me daba un error: <strong>Table &#8216;updates&#8217; was not locked with LOCK TABLES (1100)</strong></p>
<p>La solución: llamar a mysqldump con el parámetro &#8220;&#8211;lock-all-tables&#8221;</p>
<pre class="brush: plain; title: ; notranslate">
mysqldump -t -u root --lock-all-tables -p bisicalcdb_prod statuses --where=&quot;update_id in (select id from updates where timestamp &gt;='2011-12-01' and timestamp &lt; '2012-01-01')&quot; &gt; 201112_december_statuses.sql
</pre>
]]></content:encoded>
			<wfw:commentRss>http://pebbl.es/2012/01/23/usar-subconsultas-subqueries-con-mysqldump/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>10 nuevas estaciones de Valenbisi</title>
		<link>http://pebbl.es/2012/01/10/10-nuevas-estaciones-de-valenbisi/</link>
		<comments>http://pebbl.es/2012/01/10/10-nuevas-estaciones-de-valenbisi/#comments</comments>
		<pubDate>Tue, 10 Jan 2012 20:07:09 +0000</pubDate>
		<dc:creator>César</dc:creator>
				<category><![CDATA[Bisicalc]]></category>

		<guid isPermaLink="false">http://pebbl.es/?p=156</guid>
		<description><![CDATA[Desde Diciembre han aparecido 10 estaciones nuevas de Valenbisi, que ya podéis ver en el mapa de Bisicalc. Se amplía la cobertura en zonas como Tres Forques y el Barri de la Llum y se añaden estaciones a el centro. También se amplia hacia el norte y sur con nuevas estaciones en El Cabanyal y [...]]]></description>
			<content:encoded><![CDATA[<p>Desde Diciembre han aparecido 10 estaciones nuevas de Valenbisi, que ya podéis ver en <a href="http://valencia.bisicalc.com" target="_blank">el mapa de Bisicalc</a>. Se amplía la cobertura en zonas como Tres Forques y el Barri de la Llum y se añaden estaciones a el centro. También se amplia hacia el norte y sur con nuevas estaciones en El Cabanyal y Nazaret.</p>
<p>Estación 86: Gaspar Aguilar &#8211; Vicente Parra, 20 bornetas</p>
<p><img src="http://pebbl.es/wp-content/uploads/2012/01/Screen-shot-2012-01-10-at-8.16.21-PM.png" alt="" title="Screen shot 2012-01-10 at 8.16.21 PM" width="500" height="200" class="aligncenter size-full wp-image-157" /></p>
<p>Estación 258: Pintor Rafael Solves &#8211; Jose Soto Mico, 15 bornetas</p>
<p><img src="http://pebbl.es/wp-content/uploads/2012/01/Screen-shot-2012-01-10-at-8.20.53-PM.png" alt="" title="Screen shot 2012-01-10 at 8.20.53 PM" width="500" height="200" class="aligncenter size-full wp-image-158" /></p>
<p>Estación 262: Tres forques &#8211; Colonia Española de México, 19 bornetas</p>
<p><img src="http://pebbl.es/wp-content/uploads/2012/01/Screen-shot-2012-01-10-at-8.23.55-PM.png" alt="" title="Screen shot 2012-01-10 at 8.23.55 PM" width="500" height="200" class="aligncenter size-full wp-image-159" /></p>
<p>Estación 263: Padre Esteban Pernet &#8211; Casa Misericordia, 17 bornetas</p>
<p><img src="http://pebbl.es/wp-content/uploads/2012/01/Screen-shot-2012-01-10-at-8.30.09-PM.png" alt="" title="Screen shot 2012-01-10 at 8.30.09 PM" width="500" height="200" class="aligncenter size-full wp-image-160" /></p>
<p>Estación 264: Av. del Cid &#8211; Marconi, 19 bornetas</p>
<p><img src="http://pebbl.es/wp-content/uploads/2012/01/Screen-shot-2012-01-10-at-8.32.46-PM.png" alt="" title="Screen shot 2012-01-10 at 8.32.46 PM" width="500" height="200" class="aligncenter size-full wp-image-161" /></p>
<p>Estación 266: Canal de Navarrés &#8211; Maestro Rodrigo, 17 bornetas</p>
<p><img src="http://pebbl.es/wp-content/uploads/2012/01/Screen-shot-2012-01-10-at-8.36.21-PM.png" alt="" title="Screen shot 2012-01-10 at 8.36.21 PM" width="500" height="200" class="aligncenter size-full wp-image-162" /></p>
<p>Estación 40: Barcas 11, 25 bornetas </p>
<p><img src="http://pebbl.es/wp-content/uploads/2012/01/Screen-shot-2012-01-10-at-8.39.35-PM.png" alt="" title="Screen shot 2012-01-10 at 8.39.35 PM" width="500" height="200" class="aligncenter size-full wp-image-163" /></p>
<p>Estación 70: Colón 27, 17 bornetas</p>
<p><img src="http://pebbl.es/wp-content/uploads/2012/01/Screen-shot-2012-01-10-at-8.41.57-PM.png" alt="" title="Screen shot 2012-01-10 at 8.41.57 PM" width="500" height="200" class="aligncenter size-full wp-image-164" /></p>
<p>Estación 272: Vicente la Roda &#8211; Doctor Alvaro López, 16 bornetas</p>
<p><img src="http://pebbl.es/wp-content/uploads/2012/01/Screen-shot-2012-01-10-at-8.57.47-PM.png" alt="" title="Screen shot 2012-01-10 at 8.57.47 PM" width="500" height="200" class="aligncenter size-full wp-image-165" /></p>
<p>Estación 275: Moreras &#8211; Rona de Nazaret, 13 bornetas</p>
<p><img src="http://pebbl.es/wp-content/uploads/2012/01/Screen-shot-2012-01-10-at-9.04.42-PM.png" alt="" title="Screen shot 2012-01-10 at 9.04.42 PM" width="500" height="200" class="aligncenter size-full wp-image-166" /></p>
<p>Cuatro estaciones añadidas pero aún no disponibles:</p>
<p>Estación 91: Grabador Jordan &#8211; Escultor Pastor<br />
Estación 93: Blasco Ibañez &#8211; Poeta Durán Tortajada<br />
Estación 273: Moraira &#8211; Alta del Mar<br />
Estación 274: Castell de Pop &#8211; San Francisco de Paula</p>
]]></content:encoded>
			<wfw:commentRss>http://pebbl.es/2012/01/10/10-nuevas-estaciones-de-valenbisi/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Local virtual hosts y lvh.me</title>
		<link>http://pebbl.es/2012/01/03/local-virtual-hosts-y-lvh-me/</link>
		<comments>http://pebbl.es/2012/01/03/local-virtual-hosts-y-lvh-me/#comments</comments>
		<pubDate>Tue, 03 Jan 2012 11:18:39 +0000</pubDate>
		<dc:creator>César</dc:creator>
				<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://pebbl.es/?p=153</guid>
		<description><![CDATA[Una de las cosas que aprendí con la maratón de código de bisicalc es un sencillo truco para acceder a localhost sin tener que cambiar el fichero hosts. Dos situaciones en las que nos puede ser útil este truco: 1. Trabajando con una aplicación web en un host virtual de apache: Cada nuevo host virtual [...]]]></description>
			<content:encoded><![CDATA[<p>Una de las cosas que aprendí con <a href="http://pebbl.es/2011/12/17/saturday-live-code-blogueando-un-programa/" title="Saturday live code: Blogueando un programa" target="_blank">la maratón de código</a> de <a href="http://bisicalc.com" target="_blank">bisicalc</a> es un sencillo truco para acceder a <em>localhost</em> sin tener que cambiar el fichero hosts.</p>
<p>Dos situaciones en las que nos puede ser útil este truco:</p>
<p>1. Trabajando con una aplicación web en un host virtual de apache:</p>
<pre class="brush: plain; title: ; notranslate">
&lt;VirtualHost *:80&gt;
       ServerName bisicalc.local
       DocumentRoot /Users/cesar-mb/railsprojects/bisicalcdb/public
       &lt;Directory /Users/cesar-mb/railsprojects/bisicalcdb/public&gt;
           AllowOverride all
           Options -MultiViews
       &lt;/Directory&gt;
&lt;/VirtualHost&gt;
</pre>
<p>Cada nuevo host virtual sería una modificación del fichero hosts, y otra del fichero de virtual hosts de apache.</p>
<p>2. Trabajando con subdominios: barcelona.bisicalc.local, valencia.bisicalc.local, etc. Cada uno require una nueva entrada en el fichero hosts.</p>
<p>Yo tenía los dos problemas: virtual hosts y subdominios, uno por ciudad.</p>
<p>DNS al rescate. Una entrada wildcard apuntando a 127.0.0.1 y ya no hay que modificar más el fichero hosts. ¿No administras un dominio o DNS?, no hay problema. <a href="http://tbaggery.com/2010/03/04/smack-a-ho-st.html" target="_blank">Tim Pope</a> ha configurado *.smackaho.st para que apunte a 127.0.0.1. ¿Demasiado largo? *.lvh.me hace lo mismo.</p>
<p>Simplemente apunta tu browser a cualquier subdominio de lvh.me (es.lvh.me, en.lvh.me, etc.) y ambos se resolverán a localhost, sin necesidad de modificar el fichero hosts.</p>
]]></content:encoded>
			<wfw:commentRss>http://pebbl.es/2012/01/03/local-virtual-hosts-y-lvh-me/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Saturday live code: ¡Está vivo!</title>
		<link>http://pebbl.es/2011/12/17/saturday-live-code-%c2%a1esta-vivo/</link>
		<comments>http://pebbl.es/2011/12/17/saturday-live-code-%c2%a1esta-vivo/#comments</comments>
		<pubDate>Sat, 17 Dec 2011 23:11:40 +0000</pubDate>
		<dc:creator>César</dc:creator>
				<category><![CDATA[Bisicalc]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[Proyectos]]></category>

		<guid isPermaLink="false">http://pebbl.es/?p=148</guid>
		<description><![CDATA[Bueno, justo a las doce de la noche y después de unos pequeños problemas de muerte prematura y fallos iniciales, he conseguido llegar a la meta que me había propuesto esta mañana: Sacar una versión de Bisicalc para todas las ciudades españolas que exponen los datos de las bicis de alquiler. Esta semana pondré un [...]]]></description>
			<content:encoded><![CDATA[<p>Bueno, justo a las doce de la noche y después de unos pequeños problemas de muerte prematura y fallos iniciales, he conseguido llegar a <a href="http://pebbl.es/2011/12/17/saturday-live-code-blogueando-un-programa/" title="Saturday live code: Blogueando un programa">la meta que me había propuesto esta mañana</a>: Sacar una versión de Bisicalc para todas las ciudades españolas que exponen los datos de las bicis de alquiler.</p>
<p>Esta semana pondré un par de artículos sobre las cosas que he aprendido, sobre todo de Rails routing y precompilación de assets (que no termina de convencerme).</p>
<p><a href="http://pebbl.es/wp-content/uploads/2011/12/1538953234_59b4799eab.jpg"><img src="http://pebbl.es/wp-content/uploads/2011/12/1538953234_59b4799eab.jpg" alt="" title="1538953234_59b4799eab" width="398" height="500" class="aligncenter size-full wp-image-149" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://pebbl.es/2011/12/17/saturday-live-code-%c2%a1esta-vivo/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

