<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/rss2full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><rss 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:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Emili Parreño</title>
	
	<link>http://www.eparreno.com</link>
	<description>Freelance. Desarrollo de aplicaciones web en Ruby on Rails.</description>
	<pubDate>Wed, 19 Nov 2008 20:59:10 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5</generator>
	<language>en</language>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/eparreno" type="application/rss+xml" /><item>
		<title>Autotest con Growl</title>
		<link>http://feeds.feedburner.com/~r/eparreno/~3/458290138/</link>
		<comments>http://www.eparreno.com/2008/11/19/autotest-con-growl/#comments</comments>
		<pubDate>Wed, 19 Nov 2008 11:23:50 +0000</pubDate>
		<dc:creator>Emili</dc:creator>
		
		<category><![CDATA[Mac OS X]]></category>

		<category><![CDATA[Ruby on Rails]]></category>

		<category><![CDATA[autotest]]></category>

		<category><![CDATA[growl]]></category>

		<category><![CDATA[mac osx]]></category>

		<guid isPermaLink="false">http://www.eparreno.com/?p=235</guid>
		<description><![CDATA[Creamos un archivo en nuestro directorio de usuario llamado .autotest con el siguiente contenido:

require 'autotest/redgreen'
require 'autotest/html_report'
require 'autotest/menu'
module Autotest::Growl

  def self.growl msg, options={}
    salida = "growlnotify -n autotest --image \"#{options[:img]}\"  -p #{options[:pri]} -d #{rand(100)} -m \"#{msg}\" \"Tests\" #{options[:sticky]}"
    system salida
  end

  Autotest.add_hook :ran_command do &#124;at&#124;
  [...]]]></description>
			<content:encoded><![CDATA[<p>Creamos un archivo en nuestro directorio de usuario llamado .autotest con el siguiente contenido:</p>
<pre>
require 'autotest/redgreen'
require 'autotest/html_report'
require 'autotest/menu'
module Autotest::Growl

  def self.growl msg, options={}
    salida = "growlnotify -n autotest --image \"#{options[:img]}\"  -p #{options[:pri]} -d #{rand(100)} -m \"#{msg}\" \"Tests\" #{options[:sticky]}"
    system salida
  end

  Autotest.add_hook :ran_command do |at|
    results = [at.results].flatten.join("\n")
    output = results.slice(/(\d+)\s+assertions?,\s*(\d+)\s+failures?,\s*(\d+)\s+errors?/)
    failures = $~[3].to_i + $~[2].to_i
    options = (failures > 0)? {:img=>"/Users/#{ENV["USER"]}/Library/Autotest/rails_fail.png", :pri => 0, :sticky => "" } : {:img => "/Users/#{ENV["USER"]}/Library/Autotest/rails_ok.png", :pri => 0,:sticky => "" }
    if output
      growl "#{output}", options
    end
  end
end
</pre>
<p>Aquí tenéis las imágenes que se tienen que copiar en ~/Libreria/Autotest</p>
<table>
<tr>
<td>
<a href='http://www.eparreno.com/wp-content/uploads/2008/11/rails_ok.png'><img src="http://www.eparreno.com/wp-content/uploads/2008/11/rails_ok.png" alt="" title="rails_ok" width="50" height="64" class="alignnone size-medium wp-image-237" /></a></td>
<td>
<a href='http://www.eparreno.com/wp-content/uploads/2008/11/rails_fail.png'><img src="http://www.eparreno.com/wp-content/uploads/2008/11/rails_fail.png" alt="" title="rails_fail" width="50" height="64" class="alignnone size-medium wp-image-236" /></a>
</td>
</tr>
</table>
<p>Fuente: <a href="http://www.mabishu.com/blog/2008/05/07/autotest-con-advertencias-en-growl/">Mabishu</a></p>
<img src="http://feeds.feedburner.com/~r/eparreno/~4/458290138" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.eparreno.com/2008/11/19/autotest-con-growl/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.eparreno.com/2008/11/19/autotest-con-growl/</feedburner:origLink></item>
		<item>
		<title>Ponencia en la Conferencia Rails</title>
		<link>http://feeds.feedburner.com/~r/eparreno/~3/450085168/</link>
		<comments>http://www.eparreno.com/2008/11/12/ponencia-en-la-conferencia-rails/#comments</comments>
		<pubDate>Tue, 11 Nov 2008 23:32:04 +0000</pubDate>
		<dc:creator>Emili</dc:creator>
		
		<category><![CDATA[Eventos]]></category>

		<category><![CDATA[conferencia rails 2008]]></category>

		<guid isPermaLink="false">http://www.eparreno.com/?p=234</guid>
		<description><![CDATA[Como la mayoría de los que seguís este blog sabéis, este jueves y viernes se celebra en Madrid la Conferencia Rails, la reunión anual de programadores y &#8220;forofos&#8221; Rails por excelencia. Este año una de las ponencias corre a mi cargo, concretamente la titulada &#8220;Optimización, rendimiento y escalabilidad en ActiveRecord&#8220;. 
¡Nos vemos en Madrid!
]]></description>
			<content:encoded><![CDATA[<p>Como la mayoría de los que seguís este blog sabéis, este jueves y viernes se celebra en Madrid la <a href="http://www.conferenciarails.org">Conferencia Rails</a>, la reunión anual de programadores y &#8220;forofos&#8221; Rails por excelencia. Este año una de las ponencias corre a mi cargo, concretamente la titulada &#8220;<a href="http://app.conferenciarails.org/charlas/ver/78">Optimización, rendimiento y escalabilidad en ActiveRecord</a>&#8220;. </p>
<p>¡Nos vemos en Madrid!</p>
<img src="http://feeds.feedburner.com/~r/eparreno/~4/450085168" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.eparreno.com/2008/11/12/ponencia-en-la-conferencia-rails/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.eparreno.com/2008/11/12/ponencia-en-la-conferencia-rails/</feedburner:origLink></item>
		<item>
		<title>Reduce el tamaño de tus javascripts con JSMin</title>
		<link>http://feeds.feedburner.com/~r/eparreno/~3/424444184/</link>
		<comments>http://www.eparreno.com/2008/10/18/reduce-el-tamano-de-tus-javascripts-con-jsmin/#comments</comments>
		<pubDate>Sat, 18 Oct 2008 08:36:38 +0000</pubDate>
		<dc:creator>Emili</dc:creator>
		
		<category><![CDATA[Utilidades]]></category>

		<category><![CDATA[AJAX]]></category>

		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://www.eparreno.com/?p=225</guid>
		<description><![CDATA[Con el uso masivo de AJAX en las aplicaciones web, los archivos Javascript cada vez son más grandes debido al gran número de funciones que contienen. A la hora de cargar una página por primera vez, cuando aún no ha intervenido la caché sobre los archivos JS, el proceso puede ser extremadamente lento debido al [...]]]></description>
			<content:encoded><![CDATA[<p>Con el uso masivo de AJAX en las aplicaciones web, los archivos Javascript cada vez son más grandes debido al gran número de funciones que contienen. A la hora de cargar una página por primera vez, cuando aún no ha intervenido la caché sobre los archivos JS, el proceso puede ser extremadamente lento debido al gran tamaño de los archivos que tiene que descargar. </p>
<p>Para reducir el tamaño de los archivos JS disponemos de una aplicación llamada JSMin que elimina los espacios en blanco y los saltos de linea innecesarios, llegando a reducir el tamaño del archivo en algunos casos hasta la mitad.</p>
<p>Se puede descargar el código y compilarlo, bajar el ejecutable para Windows o bajarlo en diferentes lenguajes, entre los que se encuentra Ruby</p>
<p>AVISO: la conversión la hace sobre el archivo original, os recomiendo que guardéis una copia antes de aplicarle JSMin por si tuviérais que volver a modificarlo.</p>
<p><a href="http://www.crockford.com/javascript/jsmin.html">http://www.crockford.com/javascript/jsmin.html</a></p>
<img src="http://feeds.feedburner.com/~r/eparreno/~4/424444184" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.eparreno.com/2008/10/18/reduce-el-tamano-de-tus-javascripts-con-jsmin/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.eparreno.com/2008/10/18/reduce-el-tamano-de-tus-javascripts-con-jsmin/</feedburner:origLink></item>
		<item>
		<title>Optimización: mejorando las consultas MySQL en Rails (I)</title>
		<link>http://feeds.feedburner.com/~r/eparreno/~3/391040587/</link>
		<comments>http://www.eparreno.com/2008/09/13/optimizacion-mejorando-las-consultas-mysql-en-rails-i/#comments</comments>
		<pubDate>Fri, 12 Sep 2008 22:17:09 +0000</pubDate>
		<dc:creator>Emili</dc:creator>
		
		<category><![CDATA[Ruby on Rails]]></category>

		<category><![CDATA[escalabilidad]]></category>

		<category><![CDATA[optimizacion]]></category>

		<category><![CDATA[rubyonrails]]></category>

		<guid isPermaLink="false">http://www.eparreno.com/?p=224</guid>
		<description><![CDATA[Rails es un gran framework, pero la magia y la ágilidad que te proporciona tiene un precio y no es otro que la velocidad y esto se deriva en problemas de escalabilidad. Para una aplicación con poco tráfico o incluso con un tráfico medio la manera de realizar las consultas en Rails nos puede ser [...]]]></description>
			<content:encoded><![CDATA[<p>Rails es un gran framework, pero la magia y la ágilidad que te proporciona tiene un precio y no es otro que la velocidad y esto se deriva en problemas de escalabilidad. Para una aplicación con poco tráfico o incluso con un tráfico medio la manera de realizar las consultas en Rails nos puede ser suficiente, pero cuando nos encontramos con una aplicación que soporta un gran volumen de visitas o que maneja una gran cantidad de datos, las consultas &#8220;out of the box&#8221; a la base de datos se hacen cada vez más lentas hasta llegar a límites insostenibles.</p>
<p>Aquí tenéis algunos consejos para optimizar las consultas a la base de datos y conseguir aumentar considerablemente el redimiento de vuestra aplicación.<br />
<span id="more-224"></span></p>
<h3>Haz pruebas en un entorno real</h3>
<p>Las pruebas en local y con una base de datos vacía no sirven de nada. Llena tu base de datos con miles de registros y súbelo al servidor. Haz las pruebas en <em>staging</em> simulando el entorno en el que se ejecutará la aplicación.</p>
<h3>Mira la consola y los logs</h3>
<p>No cierres la consola donde lances el servidor, verás continuamente que está pasando, las consultas que ejecuta y el tiempo que tardan en ejecutarse. Pega la nariz a la pantalla y revisa linea por linea que está haciendo la aplicación en cada momento.</p>
<h3>Reduce el tamaño de los datos que estás accediendo</h3>
<p>Extrae de la tabla únicamente aquellos campos que necesitas, normalmente no necesitamos todos los campos de un modelo</p>
<pre>
User.find(:all) # No
User.find(:all, :select => "user.id, user.name, user.email")
</pre>
<h3>Reduce el número de consultas a las base de datos</h3>
<p>Vamos a mostrar diez posts y sus comentarios, la manera &#8220;normal&#8221; sería</p>
<pre>@posts = Post.find(:all, :limit => 10) # 1 consulta<br/>
@posts.comments.each do |c|
&#8230;
end # 10 consultas
</pre>
<p>Esto se puede mejorar bastante incluyendo los comentarios en la consulta donde sacamos los posts</p>
<pre>@posts = Post.find(:all, :limit => 10, :include[:comment]) # 2 consultas</pre>
<p>De esta manera nos hemos ahorrado 9 consultas y no es necesario cambiar ni úna línea de código en las vistas para mostrar los comentarios.</p>
<h3>Reduce aún más</h3>
<p>Combinado los dos ejemplo anteriores podriamos tener algo como</p>
<pre>Post.find(:all, :limit => 10, :select => "post.id, post.title, post.excerpt", :include => [:comment])</pre>
<p>Esto está muy bien, hemos reducido considerablemente el numero de accesos a la base de datos, sobretodo si el parámetro :limit es muy grande, pero aún se están cargando todos los campos del modelo asociado, en este caso los somentarios. Podemos utilizar el parámetro :joins para especificar qué campos del modelo asociado queremos</p>
<pre>
@posts = Post.find(:all, :limit => 10, :select => "post.id, post.title, post.excerpt, comment.body AS comment_body', :joins => [:comment])</pre>
<h3>Utiliza find_by_sql</h3>
<p>Algunas consultas son difíciles de optimizar, pero siempre podemos recurrir al método find_by_sql que nos permitirá realizar las consultas exactamente como las queremos.</p>
<pre>User.find_by_name("Pepe") # No
User.find_by_sql(SELECT user.* WHERE user.name = 'Pepe')</pre>
<h3>No utilices consultas complejas, mejor varias consultas simples</h3>
<p>No os volváis unos talibanes de la optimización y pretendáis hacerlo todo con una consulta enorme, a veces es mejor realizar más consultas pequeñas, ya que aunque se realicen varios accesos a la base de datos, la suma de los tiempos de latencia puede ser menor que el tiempo que tarda en ejecutarse una mega-consulta.</p>
<pre>
stuff = Stuff.find_by_sql("SELECT everything.* FROM everything JOIN (box_1, box_2) ON (everything.id = box_1.everything_id box_2.box1_id = box_1.id") # Consulta lenta

# Alternativa
boxes = Boxes.find_by_sql("SELECT box_1.everything_id FROM box_1 JOIN box_2 ON box_2.box1_id = box_1.id")

boxes.each do |box_1|
stuff = Stuff.find_by_sql("SELECT everything.* FROM everything WHERE id = #{box_1.everything_id}
end</pre>
<h3>Usa tablas MyISAM en lugar de InnoDB</h3>
<p>A no ser que necesites transacciones, bloqueos o el nivel de escrituras en tu aplicación sea muy elevado, usa MyISAM, notarás una mejora considerable del rendimiento. Cuando se realiza una migración en Rails, por defecto se crean tablas InnoDB, esto se puede cambiar en las migraciones de la siguiente manera</p>
<pre>
def self.up
     create_table :users, :options => 'engine=MyISAM' do |t|
       t.string   :name
       t.string   :surname
       t.string   :email

       t.timestamps
    end
  end
</pre>
<p>Puedes crear una migración que pase todas tus tablas InnoDB a MyISAM </p>
<pre>
class ConvertToMyIsam < ActiveRecord::Migration
  def self.up
    execute 'ALTER TABLE users ENGINE = MyISAM'
    execute 'ALTER TABLE posts ENGINE = MyISAM'
    ...
  end

  def self.down
    execute 'ALTER TABLE users ENGINE = InnoDB'
    execute 'ALTER TABLE posts ENGINE = InnoDB'
   ...
  end
end
</pre>
<h3>Utiliza cache de modelos</h3>
<p>Rails 2.1 proporciona más opciones de cache que pueden ser muy útiles para reducir el número de consultas. Supongamos que nuestra aplicación muestra siempre los diez usuarios registrados. Continuamente estaremo realizando una consulta como esta</p>
<pre>@users = User.find(:all, :limit => 10, :order => "created_at desc")</pre>
<p>Utilizando cahé podemos ahorrarnos esta consulta mientras no haya nuevos usuarios registrados. En el modelo User definimos</p>
<pre>
def self.recent_cached
  Rails.cache.fetch('User.recent_cached') { User.recent }
end

def self.recent
  User.find(:all, :limit => 10, :order => 'created_at desc')
end
</pre>
<h3>Utiliza índices</h3>
<p>En todos aquellos campos que no sean índices primarios sobre los cuales estés realizando búsquedas, crea un índice que te permita encontrarlos más rápidamente. Por ejemplo si continuamente buscas usuarios por su nickname</p>
<pre>
@user = User.find_by_sql(SELECT user.* WHERE user.nickname = 'PepeGrillo')
</pre>
<p>Crea un índice sobre el campo nickname y verás reducido el tiempo de la consulta considerablemente, sobretodo si tienes 100.000 usuarios. Crea una migración </p>
<pre>
./script/generate migration add_index_to_user
</pre>
<p>y añade el índice de esta manera</p>
<pre>
class AddIndexToUser < ActiveRecord::Migration
  def self.up
    add_index :users, :nickname
end
</pre>
<p>De momento es todo, espero que estos trucos te sirvan para poder aumentar el rendimento de tu aplicación, pero aún hay más técnicas que puedes utilizar. Las explicaré en un próximo post.</p>
<img src="http://feeds.feedburner.com/~r/eparreno/~4/391040587" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.eparreno.com/2008/09/13/optimizacion-mejorando-las-consultas-mysql-en-rails-i/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.eparreno.com/2008/09/13/optimizacion-mejorando-las-consultas-mysql-en-rails-i/</feedburner:origLink></item>
		<item>
		<title>Las 100 aplicaciones Rails con más tráfico</title>
		<link>http://feeds.feedburner.com/~r/eparreno/~3/383618745/</link>
		<comments>http://www.eparreno.com/2008/09/05/las-100-aplicaciones-rails-con-mas-trafico/#comments</comments>
		<pubDate>Thu, 04 Sep 2008 22:03:25 +0000</pubDate>
		<dc:creator>Emili</dc:creator>
		
		<category><![CDATA[Ruby on Rails]]></category>

		<category><![CDATA[escalabilidad]]></category>

		<category><![CDATA[rubyonrails]]></category>

		<guid isPermaLink="false">http://www.eparreno.com/?p=222</guid>
		<description><![CDATA[Se ha hablado mucho sobre si Ruby on Rails escala o no, sobretodo han hablado los detractores de Rails, intentando buscar argumentos para desacreditarlo.
Que una aplicación escale es la suma de muchos factores, y el más importante es el humano. No hay ni un solo lenguaje o framework que escale &#8220;out of the box&#8221;, hay [...]]]></description>
			<content:encoded><![CDATA[<p>Se ha hablado mucho sobre si Ruby on Rails escala o no, sobretodo han hablado los detractores de Rails, intentando buscar argumentos para desacreditarlo.</p>
<p>Que una aplicación escale es la suma de muchos factores, y el más importante es el humano. No hay ni un solo lenguaje o framework que escale &#8220;out of the box&#8221;, hay que meterle mano y saber lo que haces. Por tanto que alguien argumente que Rails no está a la altura de otros lenguajes por que no escala, únicamente demuestra que no sabe demasiado de que habla o que critica por criticar. </p>
<p>Si detrás del desarrollo y puesta en marcha de la aplicación hay buenos profesionales que han optimizado el código, han definido la arquitectura de sistemas correcta y han tenido en cuenta los múltiples factores que afectan al rendimiento de una aplicación, dicha aplicación va a ser escalable esté hecha en el lenguaje  o framework que sea: Rails, Java, PHP, Python&#8230;</p>
<p>Y para hechar por tierra las teorias de los que argumentan que Rails no escala, aquí os dejo un listado de las 100 aplicaciones hechas en Rails con más tráfico. Destacar que la primera, yellowpages.com, soporta <a href="http://siteanalytics.compete.com/yellowpages.com+twitter.com+flickr.com/?metric=uv">20 millones de visitas únicas al mes</a>, ahí es nada.</p>
<p><a href="http://rails100.pbwiki.com/Compete+Rankings">http://rails100.pbwiki.com/Compete+Rankings</a></p>
<img src="http://feeds.feedburner.com/~r/eparreno/~4/383618745" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.eparreno.com/2008/09/05/las-100-aplicaciones-rails-con-mas-trafico/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.eparreno.com/2008/09/05/las-100-aplicaciones-rails-con-mas-trafico/</feedburner:origLink></item>
		<item>
		<title>Instalar Git en Mac OS X Leopard</title>
		<link>http://feeds.feedburner.com/~r/eparreno/~3/320093314/</link>
		<comments>http://www.eparreno.com/2008/06/26/instalar-git-en-mac-os-x-leopard/#comments</comments>
		<pubDate>Wed, 25 Jun 2008 23:53:24 +0000</pubDate>
		<dc:creator>Emili</dc:creator>
		
		<category><![CDATA[Mac OS X]]></category>

		<category><![CDATA[Git]]></category>

		<guid isPermaLink="false">http://www.eparreno.com/?p=219</guid>
		<description><![CDATA[Mediante port la instalción resulta muy sencilla. Primero actualizamos port
sudo port selfupdate
y a continuación insalamos Git
sudo port install git-core
Una vez instalado podemos personalizarlo un poco
# Utilizar opendiff (FileMerge) para resolver los conflictos
git config --global merge.tool opendiff
# Ignorando archivos
git config --global core.excludesfile ~/.gitignore
touch              [...]]]></description>
			<content:encoded><![CDATA[<p>Mediante <em>port</em> la instalción resulta muy sencilla. Primero actualizamos <em>port</em></p>
<pre>sudo port selfupdate</pre>
<p>y a continuación insalamos <em>Git</em></p>
<pre>sudo port install git-core</pre>
<p>Una vez instalado podemos personalizarlo un poco</p>
<pre># Utilizar opendiff (FileMerge) para resolver los conflictos
git config --global merge.tool opendiff</pre>
<pre># Ignorando archivos
git config --global core.excludesfile ~/.gitignore
touch               "$HOME/.gitignore"
echo '.DS_Store' >> "$HOME/.gitignore"
echo '._*'       >> "$HOME/.gitignore"
echo '.svn'      >> "$HOME/.gitignore"
echo '.hg'       >> "$HOME/.gitignore"</code>

# Añadiendo alias
git config &#8211;global alias.st status
git config &#8211;global alias.ci commit
git config &#8211;global alias.co checkout
git config &#8211;global alias.br branch

# Un poco de color
git config &#8211;global color.ui auto</pre>
<img src="http://feeds.feedburner.com/~r/eparreno/~4/320093314" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.eparreno.com/2008/06/26/instalar-git-en-mac-os-x-leopard/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.eparreno.com/2008/06/26/instalar-git-en-mac-os-x-leopard/</feedburner:origLink></item>
		<item>
		<title>Saber si un objeto está incluido en un array</title>
		<link>http://feeds.feedburner.com/~r/eparreno/~3/314534633/</link>
		<comments>http://www.eparreno.com/2008/06/18/saber-si-un-objeto-esta-incluido-en-un-array/#comments</comments>
		<pubDate>Wed, 18 Jun 2008 10:49:38 +0000</pubDate>
		<dc:creator>Emili</dc:creator>
		
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.eparreno.com/?p=218</guid>
		<description><![CDATA[A veces es necesario saber si un objeto está incluido en un array. Supongamos que tenemos el id de un usuario y queremos saber si está incluido en un array donde tenemos los id&#8217;s de los usuarios que viven en la ciudad de Barcelona. Ruby nos proporciona una manera fácil de realizar esto:
barceloneses = User.find(:all, [...]]]></description>
			<content:encoded><![CDATA[<p>A veces es necesario saber si un objeto está incluido en un array. Supongamos que tenemos el id de un usuario y queremos saber si está incluido en un array donde tenemos los id&#8217;s de los usuarios que viven en la ciudad de Barcelona. Ruby nos proporciona una manera fácil de realizar esto:</p>
<pre>barceloneses = User.find(:all, :conditions => "city = 'Barcelona'")
user = User.find_by_name('Emili')
if barceloneses.include?(user.id)
....
end</pre>
<p>El método <italic>include?(objeto)</italic> devuelve true o false en función de si el objeto se encuentra dentro del array.</p>
<p>Más información<br />
<a href="http://www.ruby-doc.org/core/classes/Array.html">www.ruby-doc.org/core/classes/Array.html</a></p>
<img src="http://feeds.feedburner.com/~r/eparreno/~4/314534633" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.eparreno.com/2008/06/18/saber-si-un-objeto-esta-incluido-en-un-array/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.eparreno.com/2008/06/18/saber-si-un-objeto-esta-incluido-en-un-array/</feedburner:origLink></item>
		<item>
		<title>Crear usuario en Mysql y otorgarles permisos a través de la consola</title>
		<link>http://feeds.feedburner.com/~r/eparreno/~3/310311963/</link>
		<comments>http://www.eparreno.com/2008/06/12/crear-usuario-en-mysql-y-otorgarles-permisos-a-traves-de-la-consola/#comments</comments>
		<pubDate>Thu, 12 Jun 2008 10:28:43 +0000</pubDate>
		<dc:creator>Emili</dc:creator>
		
		<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://www.eparreno.com/?p=216</guid>
		<description><![CDATA[Entrar en la consola de MySQL
mysql -u root -p
grant ALL on base_de_datos.* to usuario@localhost identified by &#8216;password&#8217;;
Más información
http://www.mysql-hispano.org/page.php?id=4&#038;pag=5
http://www.webtaller.com/construccion/lenguajes/mysql/lecciones/gestion_usuarios_mysql.php
]]></description>
			<content:encoded><![CDATA[<p>Entrar en la consola de MySQL</p>
<pre>mysql -u root -p<br/>
grant ALL on base_de_datos.* to usuario@localhost identified by &#8216;password&#8217;;</pre>
<p>Más información</p>
<p><a href="http://www.mysql-hispano.org/page.php?id=4&#038;pag=5">http://www.mysql-hispano.org/page.php?id=4&#038;pag=5</a><br />
<a href="http://www.webtaller.com/construccion/lenguajes/mysql/lecciones/gestion_usuarios_mysql.php">http://www.webtaller.com/construccion/lenguajes/mysql/lecciones/gestion_usuarios_mysql.php</a></p>
<img src="http://feeds.feedburner.com/~r/eparreno/~4/310311963" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.eparreno.com/2008/06/12/crear-usuario-en-mysql-y-otorgarles-permisos-a-traves-de-la-consola/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.eparreno.com/2008/06/12/crear-usuario-en-mysql-y-otorgarles-permisos-a-traves-de-la-consola/</feedburner:origLink></item>
		<item>
		<title>Recursos anidados (o no) en REST</title>
		<link>http://feeds.feedburner.com/~r/eparreno/~3/297439000/</link>
		<comments>http://www.eparreno.com/2008/05/25/recursos-anidados-o-no-en-rest/#comments</comments>
		<pubDate>Sat, 24 May 2008 22:55:58 +0000</pubDate>
		<dc:creator>Emili</dc:creator>
		
		<category><![CDATA[Ruby on Rails]]></category>

		<category><![CDATA[rails]]></category>

		<category><![CDATA[REST]]></category>

		<guid isPermaLink="false">http://www.eparreno.com/?p=215</guid>
		<description><![CDATA[La filosofía REST permite relacionar los recursos entre ellos de manera que los podamos anidar para que únicamente tengan sentido en un contexto determinado. Supongamos que tenemos un blog multiusuario donde hay &#8220;users&#8221;, &#8220;posts&#8221; y &#8220;comments&#8221;. No tiene demasiado sentido acceder a un comentario directamente con una url del tipo /comments/34, ya que un comentario [...]]]></description>
			<content:encoded><![CDATA[<p>La filosofía REST permite relacionar los recursos entre ellos de manera que los podamos anidar para que únicamente tengan sentido en un contexto determinado. Supongamos que tenemos un blog multiusuario donde hay &#8220;users&#8221;, &#8220;posts&#8221; y &#8220;comments&#8221;. No tiene demasiado sentido acceder a un comentario directamente con una url del tipo /comments/34, ya que un comentario no tiene sentido sin un post, y lo mismo pasa con los posts.<br />
<span id="more-215"></span><br />
Lo ideal sería disponer de una url para acceder a los recursos con un formato como este:</p>
<p>/users/4/posts/34/comments/10</p>
<p>Lo que devolvería el comentario 10 que pertenece al post 34 que a su vez pertence al usuario 4. Una de las ventajas de anidar los recursos es que podemos hacer esto:</p>
<p>/users/30/posts</p>
<p>y nos devuelve todos los posts del usuario 30.</p>
<p>Como véis tiene mucho sentido anidar los recursos para relacionarlos entre ellos. Si queréis saber más sobre recursos anidados podéis consultar:</p>
<p><a href="http://www.norellana.com/2007/07/28/recursos-anidados-en-rails/" target="_blank">http://www.norellana.com/2007/07/28/recursos-anidados-en-rails/</a></p>
<p><a href="http://www.jaimeiniesta.com/2007/12/22/tutorial-recursos-anidados-con-rest-y-rails-2/" target="_blank">http://www.jaimeiniesta.com/2007/12/22/tutorial-recursos-anidados-con-rest-y-rails-2/ </a></p>
<p>Bien, el problema aparece cuando necesitamos tener un recurso que sea anidado en algunas ocasiones y que no lo sea en otras. Me explico. Supongamos una aplicación con empresas que publican ofertas de empleo. Las ofertas de empleo están anidadas a los usuarios ya que una oferta pertenece a una empresa. Así podremos acceder a las ofertas de la siguiente manera</p>
<p>/companies/34/jobs/889</p>
<p>¿Pero que pasa cuando queremos mostrar un listado de todas las ofertas? O lo que es lo mismo, hacer la petición</p>
<p>/jobs</p>
<p>Rails nos va a dar un error ya que necesita saber el id de la empresa para poder listar las ofertas de trabajo. Para poder crear un recurso anidado (o no) según nos convenga hay que hacer lo siguiente:</p>
<p>En el routes.rb crear las rutas</p>
<pre>
map.resources :companies do |company|
   company.resources :jobs
end

map.resources :jobs</pre>
<p>Cambiamos el método index del controlador</p>
<pre>
def index
   @jobs = target.find(:all)
end</pre>
<p>y añadimos los siguientes métodos</p>
<pre>protected
def target
   @user ? @user.jobs : Job
end

def get_user
    return if params[:user_id].blank?
    @user = User.find(params[:user_id])
    rescue ActiveRecord::RecordNotFound
    redirect_to jobs_url
  end

def get_job
    @job = Job.find(:all)
end</pre>
<p>De esta manera si se accede a una oferta de empleo se ejecutará el método get_user que devolverá el id del usuario para poder acceder al recurso anidado, si se está accediendo directamente al listado de ofertas de empleo, get_user hará un return y se ejecutará el código de get_job, de manera que  obtendremos el listado de ofertas de empleo.</p>
<p>De esta manera podemos disponer de un recurso anidado cuando lo necesitemos, pero también accesible directamente para realizar ciertas funciones.</p>
<p>Otro ejemplo es éste que propuso <a href="http://www.hashref.com/" title="Xavier Noria" target="_blank">Xavier Noria</a> en la lista de Rails:</p>
<p>Hay que tener presente que las URLs que dan acceso a un mismo recurso<br />
pueden ser multiples, por ejemplo</p>
<pre>/releases/my-app-1.1.tar.gz

/releases/latest.tar.gz</pre>
<p>Las URLs con caminos que indican jerarquía pueden indicar nesting (pertenencia), scope, y en general lo que tenga sentido en la aplicacion.</p>
<p>Pero supongamos ahora que estás en una central de reservas de hoteles. Para hacer una reserva puede quedar bien una URLS así:</p>
<pre>POST /chains/sol-melia/hotel/54/bookings</pre>
<p>Eso daría una reserva. En una aplicación web podrías ir al show de esa reserva despues. Si estuvieramos en un web service devolveríamos un 201 Created con una cabecera Location a la dirección de ese recurso nuevo. Esa dirección puede perfectamente ya no reflejar la jerarquia (aunque podría hacerlo y se pueden ofrecer ambos accesos):</p>
<pre>GET /bookings/789123</pre>
<p>Por ejemplo, cancelar una reserva es más fácil que se ofrezca como</p>
<pre>DELETE /bookings/789123</pre>
<p>a no ser que el cliente deba añadir la jerarquía que es redundante y puede que le suponga un GET previo. La reserva ya sabe a quien pertenece.</p>
<p>En una API así, BookingsController ha de estar preparado para servir peticiones con scope y sin scope. Si las consultas y las cancelaciones solo son accesibles con URLs directas entonces show y destroy no han<br />
de lidiar con el scope opcional. Si index se publica con y sin scope entonces la acción debe entender ambas llamadas.</p>
<img src="http://feeds.feedburner.com/~r/eparreno/~4/297439000" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.eparreno.com/2008/05/25/recursos-anidados-o-no-en-rest/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.eparreno.com/2008/05/25/recursos-anidados-o-no-en-rest/</feedburner:origLink></item>
		<item>
		<title>Cómo cargar determinadas fixtures en la base de datos</title>
		<link>http://feeds.feedburner.com/~r/eparreno/~3/295773061/</link>
		<comments>http://www.eparreno.com/2008/05/22/como-cargar-determinadas-fixtures-en-la-base-de-datos/#comments</comments>
		<pubDate>Thu, 22 May 2008 11:53:41 +0000</pubDate>
		<dc:creator>Emili</dc:creator>
		
		<category><![CDATA[Ruby on Rails]]></category>

		<category><![CDATA[fixtures]]></category>

		<category><![CDATA[rails]]></category>

		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://www.eparreno.com/?p=214</guid>
		<description><![CDATA[En algunos casos nos puede venir bien cargar el contenido de determinadas fixtures de la base de datos, por ejemplo si subimos una aplicación a producción y queremos cargar usuarios, categorías etc. Ponemos los datos en la fixture correspondiente y ejecutamos
rake db:fixtures:load FIXTURES=users,categories
Si no especificamos la variable RAILS_ENV lo cargará en la base de datos [...]]]></description>
			<content:encoded><![CDATA[<p>En algunos casos nos puede venir bien cargar el contenido de determinadas fixtures de la base de datos, por ejemplo si subimos una aplicación a producción y queremos cargar usuarios, categorías etc. Ponemos los datos en la fixture correspondiente y ejecutamos</p>
<pre>rake db:fixtures:load FIXTURES=users,categories</pre>
<p>Si no especificamos la variable RAILS_ENV lo cargará en la base de datos del entorno en el que nos encontramos, si no debe ser así podemos ejecutar</p>
<pre>rake db:fixtures:load FIXTURES=users RAILS_ENV=production</pre>
<img src="http://feeds.feedburner.com/~r/eparreno/~4/295773061" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.eparreno.com/2008/05/22/como-cargar-determinadas-fixtures-en-la-base-de-datos/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.eparreno.com/2008/05/22/como-cargar-determinadas-fixtures-en-la-base-de-datos/</feedburner:origLink></item>
	</channel>
</rss>
