<rss version="2.0" 
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:content="http://purl.org/rss/1.0/modules/content/" 
>
<channel>
<title>in web we trust</title>
<link>http://www.inwebwetrust.net</link>
<description>Fernando Blat's blog, developer at &lt;a href=&quot;http://www.lacoctelera.com&quot;&gt;La Coctelera&lt;/a&gt;.</description>
<language>es-es</language>



<image>
	<url>http://4.lcassets.com/myfiles/inwebwetrust/pies65x65.jpg</url>
	<title>in web we trust</title>
	<link>http://www.inwebwetrust.net</link>
</image>
<generator>the-shaker v0.1. More on http://www.the-shaker.com</generator>


<item>
<title>Query memcached</title>
<link>http://www.inwebwetrust.net/post/2008/09/08/query-memcached</link>
<pubDate>2008-09-08T00:57:46+00:00</pubDate>
<category domain="http://www.inwebwetrust.net">Ruby on Rails</category>
<content:encoded><![CDATA[<p>The last month I have been working in <a href="http://github.com/ferblape/query_memcached">Query Memcached</a>, a plugin that replaces the Query Cache that comes with Rails, adding a Memcache layer for persisting the query's cache between requests. That means that the cache does not expire at the end of the request, because it is stored in Memcached.</p>
<p>If you are not familiar with <a href="http://www.railsenvy.com/2007/3/20/ruby-on-rails-caching-tutorial-part-2#activerecordcaching">Query Cache</a>, you only have to know that it's a very simple caching system from ActiveRecord that stores in memory all the queries performed during a request. If a query is fired more than one time, it will be in cache, so the database won't be affected.</p>
<p>The adventages of my approach are evident: you only use the database when some table has been modified or when a new query is executed. So you can get a notice an important speed improvement.</p>
<p>It is ideal for pages which have a lot of customization for the user logged in the application: in that cases it is very difficult to cache fragments or pages, because of the expiring of all that cache, and so many things.</p>
<h3>Cache expiring</h3>
<p>For expiring this cache, each Memcached key contains a sum of all the version numbers of the tables involved in the query. If one of that tables is modified, then the version number for that table is increased.</p>
<p>For example, the query below involves the table <em>items</em> and the table <em>places</em>:</p>
<p>So, the version for the cache of that query will be the sum of the cache version of the table <em>items</em> and the cache version of the table <em>places</em>.</p>
<h3>Disclaimer</h3>
<p>We are using this plugin in two on-line web projects: <a href="http://unvlog.com">unvlog.com</a> and <a href="http://iwannagothere.net">iwannagothere</a>, and everything seems to work fine (and faster than before), but these sites don't have so much traffic (about 30.000 req/day), so, there are stille possibilities that appear bugs and "unexpected behaviours".</p>
<p>In spite of all that, if you still are encouraged to try feel free to ask me anythin.</p>
<p>More information at <a href="http://github.com/ferblape/query_memcached/tree/master/README.markdown">README</a>.</p>
]]></content:encoded>
<comments>
http://www.inwebwetrust.net/post/2008/09/08/query-memcached#comentarios
</comments>
</item>

<item>
<title>Cache testing in Rails 2</title>
<link>http://www.inwebwetrust.net/post/2008/09/06/cache-testing-in-rails-2</link>
<pubDate>2008-09-06T16:14:46+00:00</pubDate>
<category domain="http://www.inwebwetrust.net">Ruby on Rails</category>
<category domain="http://www.inwebwetrust.net">Testing</category>
<content:encoded><![CDATA[<p>At least this week I had some time to spent in ending a litte small project: adapt and improve the <a href="http://blog.cosinux.org/pages/page-cache-test">cache_test</a> plugin to Rails 2.x. You can find it at GitHub: <a href="http://github.com/ferblape/cache_test/tree/master">cache_test</a>.</p>
<p>Cache test is a very useful plugin that allows you to test if action/fragment/page cache is generated or expired during a request. For me is very surprisingly that Rails hasn't <code>asserts</code> for testing the cache, specially when, if your application uses cache, it can be the cause of its malfunctioning. Apart of that cache is so tedious to debug.</p>
<p>The way it works is very easy:</p>
<pre name="code" class="ruby">     assert_cache_fragment({:fragment => 'total_posts'}) do       get :index, :user_id => users(:first)       assert_response :success     end </pre>
<p>In my plugin I have adapted the cache storage definition to Rails 2.x (moved to <code>ActiveSupport</code>, etc), added more asserts and some tests.</p>
<p>Enjoy it!</p>
<p>More info in the <a href="http://github.com/ferblape/cache_test/tree/master/README.markdown">README</a>.</p>
]]></content:encoded>
<comments>
http://www.inwebwetrust.net/post/2008/09/06/cache-testing-in-rails-2#comentarios
</comments>
</item>

<item>
<title>bb-ruby, a small BBCode to HTML parser in Ruby</title>
<link>http://www.inwebwetrust.net/post/2008/08/23/bb-ruby-small-bbcode-to-html-parser-in-ruby</link>
<pubDate>2008-08-23T21:37:24+00:00</pubDate>
<category domain="http://www.inwebwetrust.net">Ruby on Rails</category>
<content:encoded><![CDATA[<p>These days I have been working in a small parser to convert BBCode to HTML in Ruby.</p>
<p>The motivation was that I need it (of course), and there wasn't anything complete enough. So I found <a href="http://github.com/cpjolicoeur/bb-ruby">bb-ruby</a> at GitHub and I decided to complete it with more tags, tests, and some stuff for doing it more flexible.</p>
<p>The result is a fork that you can find here:</p>
<p><a href="http://github.com/ferblape/bb-ruby/tree/master">http://github.com/ferblape/bb-ruby/tree/master</a></p>
<p>You can read the <a href="http://github.com/ferblape/bb-ruby/tree/master/README.markdown">README file</a> for getting more information.</p>
]]></content:encoded>
<comments>
http://www.inwebwetrust.net/post/2008/08/23/bb-ruby-small-bbcode-to-html-parser-in-ruby#comentarios
</comments>
</item>

<item>
<title>Redefine the run method of Test::Unit::TestCase</title>
<link>http://www.inwebwetrust.net/post/2008/08/19/redefine-the-run-method-of-test-unit-testcase</link>
<pubDate>2008-08-19T08:26:32+00:00</pubDate>
<category domain="http://www.inwebwetrust.net">Ruby on Rails</category>
<category domain="http://www.inwebwetrust.net">Ruby</category>
<content:encoded><![CDATA[<p>A small snippet for testing.</p>
<p>If you want to add some special actions before and after the execution of each test, and don't want to add it to <code>setup</code> and <code>teardown</code> because you will be repeating your code for each unit test and functional test, or because it is a block, you can do an <code>alias_method_chain</code> for the <strong><code>run</code> method</strong>:</p>
<pre name="code" class="ruby"> module Test   module Unit     class TestCase               def run_with_my_block(*args, &block)         Cache.clean # code before                  a_block_that_you_want_to_execute do            run_without_my_block(*args, &block)         end                  # Code after       end        alias_method_chain :run, :my_block      end   end end </pre>
<p>You can redefine it at the beginning of your <code>test_helper.rb</code> for example.</p>
<p>Note that this code is only for Rails, becaus of the use of <code>alias_method_chain</code> function.</p>
]]></content:encoded>
<comments>
http://www.inwebwetrust.net/post/2008/08/19/redefine-the-run-method-of-test-unit-testcase#comentarios
</comments>
</item>

<item>
<title>Generating static maps with attachment_fu and static-gmaps gem</title>
<link>http://www.inwebwetrust.net/post/2008/08/18/generating-static-maps-with-attachment-fu-and-static-gmaps-gem</link>
<pubDate>2008-08-18T16:10:05+00:00</pubDate>
<category domain="http://www.inwebwetrust.net">Ruby on Rails</category>
<category domain="http://www.inwebwetrust.net">Desarrollo Web</category>
<category domain="http://www.inwebwetrust.net">Snippets y Trucos</category>
<content:encoded><![CDATA[<p><a href="http://maps.google.com/">Google Maps</a> is, may be, the coolest service for integrating maps in your web applications: it offers a <a href="http://code.google.com/apis/maps/">powerful and easy API</a> with no limit usage.</p>
<p>The problem is that it loads quite Javascript that has to connect to the main Google Maps page in order to draw our map. In order to avoid that we can use <a href="http://code.google.com/apis/maps/documentation/staticmaps/">static Google Maps</a>, it is, a picture (generated in real time) of the map we want to visualize. The problem with this is that you can't interact with the map (because it is an image) and that there is a limitation per day. But may be you find it useful in a particular moment.</p>
<p>For example, in <a href="http://iwannagothere.net">iwannagothere.net</a> we have a small map in every place that shows the location of that city:</p>
<p><img class="imgCen" src="http://www.inwebwetrust.net/myfiles/inwebwetrust/valencia-iwanna.png" alt="" width="552" height="453" /></p>
<p>In that situation we can change the map because the map is not for navigating along the city. For that you have a map in each item.</p>
<p>In Ruby on Rails, the programming framework of iwannagothere.net there is a gem called <a href="http://static-gmaps.rubyforge.org/">static-gmaps</a> that does the hard work for you. What's more, we have found the way to integrate this maps with <a href="http://svn.techno-weenie.net/projects/plugins/attachment_fu/">attachment_fu</a>, in order you save a copy of the map in your filesystem and then avoid the day limitation usage.</p>
<p>Basically we have an attachment_fu kind of model (nothing special here):</p>
<pre class="ruby" name="code">class PlaceMap &lt; ActiveRecord::Base   belongs_to :place    has_attachment  :content_type =&gt; :image,                    :storage =&gt; :file_system,                   :processor=&gt; :rmagick,                   :path_prefix =&gt; 'public/userfiles/place_maps',                    :max_size =&gt; 1.megabyte    validates_as_attachment   end </pre>
<p>The we generate the static map instance:</p>
<pre class="ruby" name="code">	 map = StaticGmaps::Map.new :center   =&gt; [ place.lat, place.long ],                             :zoom     =&gt; 12,                             :size     =&gt; [ 334, 144 ],                             :key      =&gt; APP['gmkey']   </pre>
<p>And save it in our <code>PlaceMap</code> model:</p>
<pre class="ruby" name="code"> PlaceMap.create(:uploaded_data =&gt; (open(map.url)), :place_id =&gt; place.id, :content_type =&gt; 'image/gif') </pre>
<p>The problem here is that we are not uploading a file in the usual way: we are trying to save a raw of data. Attachment_fu doesn't know how to do that, so we have to apply a little patch:</p>
<pre class="ruby" name="code"> module Technoweenie   module AttachmentFu     module InstanceMethods        def uploaded_data=(file_data)         return nil if file_data.nil? || file_data.size == 0         self.content_type = file_data.content_type         self.filename     = Time.now.to_i.to_s+'.gif'         if file_data.is_a?(StringIO)           file_data.rewind           self.temp_data = file_data.read         else           self.temp_path = file_data         end       end                end   end end </pre>
<p>Here we are giving a random filename, generated from the current time.</p>
<p>And that's all, really easy :)</p>
]]></content:encoded>
<comments>
http://www.inwebwetrust.net/post/2008/08/18/generating-static-maps-with-attachment-fu-and-static-gmaps-gem#comentarios
</comments>
</item>

<item>
<title>iwannagothere.net, a different way of traveling</title>
<link>http://www.inwebwetrust.net/post/2008/08/17/iwannagothere-net-different-way-of-traveling</link>
<pubDate>2008-08-17T21:42:07+00:00</pubDate>
<content:encoded><![CDATA[<p><img class="imgCen" src="http://www.inwebwetrust.net/myfiles/inwebwetrust/nlogo.png" alt="" /></p>
<p><a href="http://iwannagothere.net">iwannagothere.net</a> is the last project from <a href="http://mamuso.net">mamuso</a>, <a href="http://www.limalimon.com.es">Maria</a> and me. It's a site about <strong>traveling</strong> with two main purposes:</p>
<ol>
<li>share all the special places you have discovered in your travels: a singular monument, a delicious and cheap restaurant, a small museum with special charm, a park where you can see the most wonderful sunset ever...</li>
<li>help you to prepare your travels with all the information uploaded in the site</li>
</ol>
<p>It's a kind of independent and high quality information travel guide.</p>
<p>As in <a href="http://unvlog.com">unvlog.com</a> we developed it in Ruby on Rails, (now running version 2.1), in our free time, along 3 months. Now we are refining a lot of details, and adapting some parts that we have seen people don't use as we thought.</p>
<p>We are going to explain all the technical issues we had in a serie of small posts in this blog or in the <a href="http://blog.iwannagothere.net/">iwannagothere's blog</a>. As well, we are going to present it at <a href="http://www.conferenciarails.org/">Spanish Rails Conference 08</a> in November.</p>
<p>We hope you enjoy the site and find it useful.</p>
]]></content:encoded>
<comments>
http://www.inwebwetrust.net/post/2008/08/17/iwannagothere-net-different-way-of-traveling#comentarios
</comments>
</item>

<item>
<title>Writing in English</title>
<link>http://www.inwebwetrust.net/post/2008/08/17/writing-in-english</link>
<pubDate>2008-08-17T21:40:07+00:00</pubDate>
<content:encoded><![CDATA[<p>I think that the moment has arrived. This blog switches to English (to my bad English, that surely all Spanish will understand), because this is the only way to participate in the conversation of the international community.</p>
]]></content:encoded>
<comments>
http://www.inwebwetrust.net/post/2008/08/17/writing-in-english#comentarios
</comments>
</item>

<item>
<title>Comprobar si una relacíon contiene un elemento</title>
<link>http://www.inwebwetrust.net/post/2008/06/09/comprobar-si-relacion-esta-vacia</link>
<pubDate>2008-06-09T18:28:04+00:00</pubDate>
<category domain="http://www.inwebwetrust.net">Ruby on Rails</category>
<category domain="http://www.inwebwetrust.net">Snippets y Trucos</category>
<content:encoded><![CDATA[<p>Muchas veces cuando trabajamos con ActiveRecord nos olvidamos / ignoramos qué hace por debajo.</p>
<p>Un claro ejemplo lo encontramos cuando tenemos una relación <code>:has_many</code> y queremos comprobar si un elemento está incluída en dicha relación.</p>
<p>Por ejemplo:</p>
<pre name="code" class="ruby"> class Place < ActiveRecord::Base   has_many :items end </pre>
<pre name="code" class="ruby"> class Item < ActiveRecord::Base   belongs_to :place end </pre>
<p>Seguro que más de una vez, para comprobar que un <em>place</em> contiene un <em>ítem</em> hemos utilizado el "rubysta" <code>include?</code>:</p>
<pre name="code" class="ruby"> place.items.include?(item) </pre>
<p>Pensándolo fríamente 0.2 segundos nos damos cuenta de que estamos cargando un array con todos los elementos de una relación, que pueden ser 10 o pueden ser 1.000.000. Y ya sabemos lo generoso que es Ruby con la memoria que toma y que nunca deja ir.</p>
<p>Un truco para evitar que esto suceda sin dejar de utilizar <code>include?</code> es definir dicho método dentro de la relación tal que así:</p>
<pre name="code" class="ruby"> class Place < ActiveRecord::Base   has_many :items do      def include?(item)       count(:conditions => ["item_id = ?", item.id]) > 0     end   end end </pre>
<p>Es decir, resolvemos el problema con un simple <code>COUNT</code> de Mysql.</p>
<p>¿Alguien se anima a hacer un plugin? Creo que sería bastante inmediato para cuando se cumplen las convenciones y sabemos que la clave foránea de la relación es <em>singular del nombre de la relación</em>_id. O quizá ni eso, si encontramos la forma de preguntarle a ActiveRecord cuál es la clave foránea de una relación.</p>
]]></content:encoded>
<comments>
http://www.inwebwetrust.net/post/2008/06/09/comprobar-si-relacion-esta-vacia#comentarios
</comments>
</item>

<item>
<title>Visualizar en el log de producción las querys lentas</title>
<link>http://www.inwebwetrust.net/post/2008/06/05/visualizar-el-log-produccion-querys-lentas</link>
<pubDate>2008-06-05T11:57:42+00:00</pubDate>
<category domain="http://www.inwebwetrust.net">Ruby on Rails</category>
<category domain="http://www.inwebwetrust.net">Snippets y Trucos</category>
<content:encoded><![CDATA[<p>Cuando tienes una aplicación en producción es más que necesario controlar los tiempos de las peticiones más lentas.</p>
<p>Sin embargo muchas veces con el log de Rails no es suficiente, y hay que alcanzar un mayor nivel de detalle.</p>
<p>El log en modo <code>debug</code> nos da todo el detalle que necesitamos, pero mostrando demasiada información (¿de qué nos sirve saber que un <code>SELECT</code> sencillo tarda 0.001 segundos?).</p>
<p>Pero si en ese log pudiéramos filtrar las consultas SQL más lentas sí que tendríamos información de consultas lentas asociadas a cada petición al servidor.</p>
<p>Gracias al plugin <a href="http://github.com/ntalbott/query_trace/tree/master">query trace</a> y a una pequeña modificación podemos mostrar qué consultas tardan más de 1 segundo:</p>
<pre name="code" class="ruby"> module ActiveRecord   module ConnectionAdapters     class AbstractAdapter       def log_info(sql, name, runtime)         return unless @logger         @logger.info(           format_log_entry(             "#{name.nil? ? "SQL" : name} (#{sprintf("%f", runtime)})",             sql.gsub(/ +/, " ")           )         ) if (RAILS_ENV == 'production' && runtime > 1.0) || RAILS_ENV != 'production'       end     end   end end </pre>
<p>Este código lo he probado en Rails 1.2.x, no sé si funcionará en otras versiones.
</p>
]]></content:encoded>
<comments>
http://www.inwebwetrust.net/post/2008/06/05/visualizar-el-log-produccion-querys-lentas#comentarios
</comments>
</item>

<item>
<title>Diferencias colorizadas en SVN y GIT</title>
<link>http://www.inwebwetrust.net/post/2008/05/31/diferencias-colorizadas-svn-y-git</link>
<pubDate>2008-05-31T06:31:57+00:00</pubDate>
<category domain="http://www.inwebwetrust.net">Snippets y Trucos</category>
<content:encoded><![CDATA[<p>Si trabajáis con control de versiones una de las operaciones más habituales es ver las modificaciones de un fichero. Eso en Subversion se hace con <code>svn diff</code>. </p>
<p>Sin embargo yo utilizo un script que creo que me pasó <a href="http://www.lacoctelera.com/porras">porras</a> para que me muestre en colores las modificaciones.</p>
<p>El script es este:</p>
<pre><code class="ruby"> #!/usr/bin/env ruby  `svn diff #{ARGV.join(' ')}`.each do |line|   puts( if line =~ /^\+(.*)$/         "\e[32m#{$&}\e[0m"         elsif line =~ /^-(.*)$/           "\e[31m#{$&}\e[0m"         else           line         end       ) end </code></pre>
<p>Con darle permisos de ejecución ya podéis tener un <code>svndiff</code> por ejemplo.</p>
<p>No pongo el equivalente en git porque es bastante inmediato.
</p>
]]></content:encoded>
<comments>
http://www.inwebwetrust.net/post/2008/05/31/diferencias-colorizadas-svn-y-git#comentarios
</comments>
</item>

<item>
<title>Límites en claves y valores de Memcached</title>
<link>http://www.inwebwetrust.net/post/2008/02/24/limites-claves-y-valores-memcached</link>
<pubDate>2008-02-24T12:13:14+00:00</pubDate>
<category domain="http://www.inwebwetrust.net">Ruby on Rails</category>
<content:encoded><![CDATA[<p>Una cuestión que hay que tener presente a la hora de trabajar con Memcached y que no se suele tener en cuenta es el tamaño de las claves y los valores:</p>
<ul>
<li><strong>claves</strong>: máximo de 250 caracteres</li>
<li><strong>valores alojados</strong>: máximo 1 Megabyte</li>
</ul>
<p>Es muy difícil que una aplicación Rails las claves generadas a partir de las URL's tengan tanto tamaño, pero puede darse el caso y hay que tenerlo presente.</p>
<p>En el grupo de discusión <a href="http://groups.google.com/group/acts_as_cached?hl=en">acts_as_cached</a> esta semana han propuesto <em>hashear</em> (con MD5, por ejemplo) las claves antes de guardarlas para curarnos en salud.</p>
]]></content:encoded>
<comments>
http://www.inwebwetrust.net/post/2008/02/24/limites-claves-y-valores-memcached#comentarios
</comments>
</item>

<item>
<title>Sirviendo feeds cacheados con Nginx directamente</title>
<link>http://www.inwebwetrust.net/post/2008/01/16/sirviendo-feeds-cacheados-con-nginx-directamente</link>
<pubDate>2008-01-16T00:02:58+00:00</pubDate>
<category domain="http://www.inwebwetrust.net">Snippets y Trucos</category>
<content:encoded><![CDATA[<p>Reconozco que me ha constado dios y ayuda dar con la regla adecuada, así que por eso me he decidido a postearla.</p>
<p>El problema es el siguiente: en <a href="http://unvlog.com">unvlog.com</a> (sí, ese proyecto del que no he hablado) somos muy Rails y tenemos para todos los recursos que tiene sentido una ruta que responde a un formato u otro según se le solicite pero con esta forma:</p>
<p>En concreto, esta URL corresponde al feed de un blog, feed que está cacheado en disco gracias a la <strong>caché de página</strong> de Rails. Pues bien, la idea es que el servidor web sirva directamente esta caché, así que una regla podría ser:</p>
<pre name="code">   if (-f /cache/$request_filename) {           rewrite (.*) /cache/$1 break;   } </pre>
<p>(Esto, asumiendo que tenemos la caché en <strong><code>public/cache</code></strong>)</p>
<p>El problema es que esta regla no funciona, y creo que se debe a que <strong>blat.atom</strong> lleva un '.' y no es capaz de asignar la URL a la variable <code>$request_filename</code>.</p>
<p>Al final ha sido tan fácil como utilizar otra variable que he encontrado en la parte rusa del wiki, <code>$request_uri</code>:</p>
<pre name="code">   if (-f $document_root/cache/$request_uri) {           rewrite ^/(.*).atom$ /cache/$1.atom break;   } </pre>
<p>Con esto ha funcionado perfectamente y ya tenemos cacheados y servidos por Nginx los feeds en <a href="http://unvlog.com">unvlog.com</a>.</p>
]]></content:encoded>
<comments>
http://www.inwebwetrust.net/post/2008/01/16/sirviendo-feeds-cacheados-con-nginx-directamente#comentarios
</comments>
</item>

<item>
<title>Comprendiendo las estadísticas del Memcached</title>
<link>http://www.inwebwetrust.net/post/2008/01/15/comprendiendo-estadaasticas-del-memcached</link>
<pubDate>2008-01-15T22:30:50+00:00</pubDate>
<category domain="http://www.inwebwetrust.net">Ruby</category>
<content:encoded><![CDATA[<p><a href="http://www.danga.com/memcached/">Memcached</a> (o Memcache) incorpora un sistema de estadísticas interno que nos permite conocer el estado del demonio, su capacidad restante de almacenamiento, uso, conextiones, etcétera.</p>
<p>Para acceder a él a través del cliente de Ruby, por ejemplo, basta con cargar una consola en el entorno deseado e invocar al método <code class="ruby">stats</code> del objeto de caché.</p>
<p>Por ejemplo, si nuestra configuración es la siguiente:</p>
<pre><code class="ruby">   CACHE = MemCache.new 'localhost:11211', :namespace => 'wadus_fragments' </code></pre>
<p>Podemos utilizar el objeto <code>CACHE</code> de la siguiente manera:</p>
<pre><code class="ruby">   pp CACHE.stats   {"bytes"=>746532339,    "pid"=>10303,    "connection_structures"=>19,    "time"=>1200349556,    "limit_maxbytes"=>1073741824,    "cmd_get"=>689486,    "version"=>"1.1.12",    "bytes_written"=>3296488315,    "cmd_set"=>265986,    "get_misses"=>265168,    "total_connections"=>1238,    "curr_connections"=>17,    "curr_items"=>66977,    "uptime"=>56490,    "get_hits"=>424318,    "total_items"=>265986,    "rusage_system"=>95.012555,    "rusage_user"=>17.16339,    "bytes_read"=>3226552602} </code></pre>
<p>La interpretación de todos estos valores se puede encontrar en <a href="http://code.sixapart.com/svn/memcached/trunk/server/doc/protocol.txt">la definición del protocolo</a>:</p>
<pre>   Name              Type     Meaning   ----------------------------------   pid               32u      Process id of this server process   uptime            32u      Number of seconds this server has been running   time              32u      current UNIX time according to the server   version           string   Version string of this server   pointer_size      32       Default size of pointers on the host OS                              (generally 32 or 64)   rusage_user       32u:32u  Accumulated user time for this process                               (seconds:microseconds)   rusage_system     32u:32u  Accumulated system time for this process                               (seconds:microseconds)   curr_items        32u      Current number of items stored by the server   total_items       32u      Total number of items stored by this server                               ever since it started   bytes             64u      Current number of bytes used by this server                               to store items   curr_connections  32u      Number of open connections   total_connections 32u      Total number of connections opened since                               the server started running   connection_structures 32u  Number of connection structures allocated                               by the server   cmd_get           64u      Cumulative number of retrieval requests   cmd_set           64u      Cumulative number of storage requests   get_hits          64u      Number of keys that have been requested and                               found present   get_misses        64u      Number of items that have been requested                               and not found   evictions         64u      Number of valid items removed from cache                                                                                                         to free memory for new items                                                                                          bytes_read        64u      Total number of bytes read by this server                               from network   bytes_written     64u      Total number of bytes sent by this server to                               network   limit_maxbytes    32u      Number of bytes this server is allowed to                              use for storage.    threads           32u      Number of worker threads requested.                              (see doc/threads.txt) </pre>
<p>En concreto cuatro parámetros me han parecido interesantes de observar:</p>
<ul>
<li>el parámetro <strong><code>bytes</code></strong> junto con el de <strong><code>limit_maxbytes</code></strong>: el primero representa el total de bytes ocupados actualmente, frente el máximo. </li>
<li>el número de fallos de caché que refleja el valor del parámetro <strong><code>get_misses</code></strong> junto con el número de aciertos <strong><code>get_hits</code></strong></li>
</ul>
<p>Los primeros nos permiten saber si hemos llegado al límite el almacenamiento que necesita nuestra aplicación y el segundo nos permite saber si nuestra política de caché es adecuada: diviendo <em>hits</em> entre <em>misses</em> obtenemos la proporción de fragmentos encontrados frente a fragmentos que ya no existían. Un valor de 1 indica que por cada dos búsquedas, una tiene éxito y otra no.</p>
<p>Por supuesto un valor inferior a uno muestra que la caché no sirve de nada (indicaría por ejemplo que necesitaríamos ampliar el Memcache o que tenemos una política de borrado "exagerada").</p>
]]></content:encoded>
<comments>
http://www.inwebwetrust.net/post/2008/01/15/comprendiendo-estadaasticas-del-memcached#comentarios
</comments>
</item>

<item>
<title>Caché en Rails</title>
<link>http://www.inwebwetrust.net/post/2007/11/30/cachao-rails</link>
<pubDate>2007-11-30T14:25:33+00:00</pubDate>
<category domain="http://www.inwebwetrust.net">Ruby on Rails</category>
<category domain="http://www.inwebwetrust.net">Charlas y Presentaciones</category>
<content:encoded><![CDATA[<p>Rompo este silencio para subir una de mis charlas de la <a href="http://conferenciarails.org/" title="http://conferenciarails.org/" id=link_0>Conferencia Rails</a> :</p>
<p><a href="http://www.inwebwetrust.net/myfiles/inwebwetrust/cache.pdf">Caché en Rails</a></p>
<p>Pronto, todas las demás, colgadas en la web de la Conferencia,</p>
]]></content:encoded>
<comments>
http://www.inwebwetrust.net/post/2007/11/30/cachao-rails#comentarios
</comments>
</item>

<item>
<title>Un pequeña benchmark sobre servidores web + aplicación con Rails y Merb</title>
<link>http://www.inwebwetrust.net/post/2007/09/03/un-pequena-benchmark-sobre-servidores-web-aplicacion-con-rails</link>
<pubDate>2007-09-03T08:57:01+00:00</pubDate>
<category domain="http://www.inwebwetrust.net">Ruby on Rails</category>
<content:encoded><![CDATA[<p><a href="http://www.webficient.com/2007/08/testing-various-configurations-of-rails.html">Testing Various Configurations of Rails, Merb, Swiftiply, and Nginx</a> es una más que interesante comparativa entre el clásico Mongrel y una alternativa que ha surgido hace poco <a href="http://swiftiply.swiftcore.org/">Swiftiply</a>: un servidor <em>proxy</em> que además, nos regala una variante de Mongrel, el <em>evented Mongrel</em>, totalmente compatible, pero que basa su funcionamiento en gestión de eventos (<a href="http://rubyforge.org/projects/eventmachine">EventMachine</a>), en lugar de utilizar los clásicos <em>threads</em>.</p>
<p>Además, en el post utilizan <a href="http://wiki.codemongers.com/Main">Nginx</a> como servidor web y <a href="http://www.rubyonrails.org/">Ruby on Rails</a> y <a href="http://merb.rubyforge.org/">Merb</a>, como frameworks de desarrollo, así como Memcached para almacenar sesiones.</p>
<p>Los resultados, muy interesantes:</p>
<ul>
<li>Merb es mucho más rápido que Rails, a costa de perder parte de la magia</li>
<li>Nginx es una gran alternativa a Apache, sobretodo cuando la memoria es un recurso escaso (en mi nuevo <a href="http://www.slicehost.com/">Slicehost</a>, por ejemplo)</li>
<li>y, el más importante, el <em>evented Mongrel</em> funciona bastante mejor que el Mongrel en situaciones de alta concurrencia</li>
</ul>
<p>Así que si te gusta "jugar" y quieres probarlo, lo recomiendo: la instalación es muy sencilla y los resultados saltan a la vista.</p>
]]></content:encoded>
<comments>
http://www.inwebwetrust.net/post/2007/09/03/un-pequena-benchmark-sobre-servidores-web-aplicacion-con-rails#comentarios
</comments>
</item>

<item>
<title>Sobre httperf y las pruebas de carga</title>
<link>http://www.inwebwetrust.net/post/2007/08/18/sobre-httperf-y-pruebas-carga</link>
<pubDate>2007-08-18T20:17:05+00:00</pubDate>
<category domain="http://www.inwebwetrust.net">Ruby on Rails</category>
<category domain="http://www.inwebwetrust.net">Desarrollo Web</category>
<content:encoded><![CDATA[<p>Andaba yo viendo esta mañana el <em>screencast</em> de Peepcode <a href="http://peepcode.com/products/benchmarking-with-httperf">Benchmarking with httperf</a> bastante emocionado (ya que la fama precede a estos <em>screencasts</em>) para ver cómo podía mejorar las pruebas de rendimiento que estoy haciendo contra una aplicación Rails que he instalado en mi recién adquirido Slicehost.</p>
<p>La situación es la siguiente: es una cuenta <a href="http://www.slicehost.com/">Slicehost</a> de 256<abbr title="Megabytes">Mb</abbr> de memoria, en el que tú instalas lo que quieres. El problema es que debes de instalar un servidor web, los servidores de aplicaciones y la base de datos, y todos ellos han de luchar por esos 256Mb. Así que al final me he decidido por instalar esto:</p>
<ul>
<li><strong>servidor web</strong>: Nginx, que tenía ganas de probarlo tras leer a uno de los <em>sysadmins</em> decir que Nginx era lo más estable que había visto nunca, y que recomendaba usar Apache sólo en el caso de querer que un mismo servidor web compartiera diferentes aplicaciones y en distintos lenguajes (PHP y Rails, por ejemplo). Además, su uso de memoria es ridículo.</li>
<li><strong>servidor de aplicaciones</strong>: Mongrel. Considerando los 60Mb que viene a consumir un Mongrel de memoria, el número de Mongrels en el clúster lo he establecido a 3.</li>
<li><strong>servidor de base de datos</strong>: MySQL. No había otra opción.</li>
</ul>
<p>Además de todo esto, hay un servidor Memcached de 32Mb para guardar las sesiones.</p>
<p>Y claro, quería hacer pruebas de carga contra el stack completo para ver de rendimiento qué tal.</p>
<p>Las pruebas se han realizado contra una página sin caché y con bastantes consultas a la base de datos, cuyo tiempo de respuesta medio es de 0.005 segundos o lo que es lo mismo, unas 20 <abbr title="peticiones por segundo">req/s</abbr>.</p>
<h3>El screencast</h3>
<p>El <em>screencast</em> se queda algo corto en cuanto a uso de la herramienta <a href="http://www.hpl.hp.com/research/linux/httperf/">httperf</a>, ya que el autor pierde mucho tiempo explicando conceptos teóricos y muy básicos de Estadística: <a href="http://es.wikipedia.org/wiki/Promedio">media</a> y <a href="http://es.wikipedia.org/wiki/Desviaci%C3%B3n_est%C3%A1ndar">desviación estándar</a>, así como cómo mostrar luego los resultados a través de gráficas (unas muy bonitas generadas con <a href="http://nubyonrails.com/pages/gruff">gruff</a>).</p>
<p>Posteriormente las pruebas las realiza contra un único Mongrel, explicando con todo detalle:</p>
<ul>
<li>la importancia de utilizar datos reales: la muestra debe de ser representativa para que los resultados lo sean</li>
<li>la importancia de obtener muchas muestras: cuantas más muestras, la media y la varianza son más significativas también</li>
<li>la importancia de anotar todos los resultados</li>
<li>la importancia de la interpretación de los mismos en función de los resultados obtenidos y entender qué significan</li>
</ul>
<p>Las pruebas las realiza para comparar el rendimiento de su aplicación sin usar caché, utilizando caché de acción y utilizando caché de página. Así que establece el <em>baseline</em> en los resultados obtenidos sin utilizar caché y a partir de los obtenidos utilizando caché establece porcentajes de mejora.</p>
<h3>Otros aspectos a tener en cuenta</h3>
<p>Hay otras muchas situaciones en las que es recomendable hacer pruebas de rendimiento contra tu propia aplicación:</p>
<ul>
<li>calcular el número de Mongrels a lanzar en el servidor de aplicaciones. Una buena explicación (aunque breve también), la da Zed en la página de Mongrel: <a href="http://mongrel.rubyforge.org/docs/how_many_mongrels.html">How many Mongrels</a></li>
<li>comparar el rendimiento entre distintos sistemas de almacenamiento de sesiones</li>
<li>comparar distintos algoritmos de balanceo en el módulo de proxy</li>
<li>determinar el tope máximo de ficheros servidos a través de una unidad NFS</li>
<li>...</li>
</ul>
<p>En estos casos es posible que nos interese conocer algún parámetro más de <code>httperf</code> que los que se han explicado en el vídeo:</p>
<ul>
<li><code>--rate</code>: determinar el número de peticiones concurrentes lanzadas en un segundo</li>
<li><code>--wsess</code>: determina cada cuántas peticiones se inicia una nueva sesión</li>
</ul>
<p>Y además, si vais a hacer pruebas de carga, hay que tener en cuenta estas perogrulladas, que a veces no lo son tanto:</p>
<ol>
<li>el número de Mongrels en el clúster</li>
<li>la conexión: ¡no hagas las pruebas con un ADSL! En mi caso he pasado de 30 req/s a más de 50 req/s sólo por lanzar las pruebas desde una máquina con una conexión decente</li>
<li>testea el <em>stack</em> entero: sobre todo porque es interesante ver si hay problemas de conectividad entre una capa (web) y la otra (aplicación), o si el proxy que reparte la carga está mal configurado, etcétera</li>
</ol>
]]></content:encoded>
<comments>
http://www.inwebwetrust.net/post/2007/08/18/sobre-httperf-y-pruebas-carga#comentarios
</comments>
</item>

<item>
<title>Trabajando con BackgroundDRB en el entorno de test</title>
<link>http://www.inwebwetrust.net/post/2007/08/13/trabajando-con-backgrounddrb-el-entorno-test</link>
<pubDate>2007-08-13T12:06:26+00:00</pubDate>
<category domain="http://www.inwebwetrust.net">Ruby on Rails</category>
<category domain="http://www.inwebwetrust.net">Testing</category>
<content:encoded><![CDATA[<p><a href="http://backgroundrb.devjavu.com/">BackgrounDRB</a> es un proyecto en desarrollo que pretende crear un servicio estable para ejecutar tareas en segundo plano, sin que estas entorpezcan la navegación del usuario por la aplicación, relentizando sus tiempos de respuesta.</p>
<p>La verdad es que era un completo desconocido para mí hasta que encontré la presentación de <a href="http://spejman.blogspot.com/">Sergio Espeja</a> en la conferencia de Rails: <a href="http://bee.com.es/espeja/conferenciarails">Tareas en background con RoR y BackgrounDRb</a>.</p>
<p>En este año que ha pasado, hay una <a href="http://backgroundrb.devjavu.com/projects/backgroundrb/browser/trunk" title="http://backgroundrb.devjavu.com/projects/backgroundrb/browser/trunk" id=link_0>nueva versión</a> que corrige algunos fallos y deja otros abiertos, pero que es, dicen, bastante estable. Y la verdad es que con la anterior tuve muchos problemas para crear mis <em>workers</em> pero con esta estoy encantado.</p>
<p>Pero este post no era para hablar de las bondades del proyecto, que son muchas, sino para contar cómo hacer que en los <em>tests</em> no necesitemos tener lanzado un servidor BackgroundDRB para que estos funcionen, sino que podemos utilizar un <strong>mock</strong>.</p>
<p>He encontrado uno <a href="http://backgroundrb.devjavu.com/projects/backgroundrb/ticket/54">entre los tickets del proyecto</a>, y que se ve que aún no está incluído en la última versión.</p>
<p>Basta con descargarlo en <code>test/mocks/test</code> e incluir la siguiente línea en el <code>test_helper.rb</code>:</p>
<pre><code class="ruby"> require File.dirname(__FILE__) + '/mocks/test/backgroundrb_mock.rb' </code></pre>
<p>Y voilá, tests funcionando de nuevo.
</p>
]]></content:encoded>
<comments>
http://www.inwebwetrust.net/post/2007/08/13/trabajando-con-backgrounddrb-el-entorno-test#comentarios
</comments>
</item>

<item>
<title>Testeando helpers</title>
<link>http://www.inwebwetrust.net/post/2007/08/12/testeando-helpers</link>
<pubDate>2007-08-12T11:35:15+00:00</pubDate>
<category domain="http://www.inwebwetrust.net">Ruby on Rails</category>
<category domain="http://www.inwebwetrust.net">Testing</category>
<category domain="http://www.inwebwetrust.net">Snippets y Trucos</category>
<content:encoded><![CDATA[<p>El otro día, buscando información sobre cómo testear <em>helpers</em> en Rails di con este post: <a href="http://nubyonrails.com/articles/2006/04/07/test-your-helpers">Test your helpers</a>, en el que el autor habla de un <em>plugin</em> desarrollado por él mismo que facilita sobremanera la labor.</p>
<p>El <em>plugin</em> se llama <a href="http://topfunky.net/svn/plugins/helper_test/">helper_test</a> y es muy sencillo de utilizar:</p>
<ol>
<li>descargar</li>
<li>editar <code>tests/test_helper.rb</code> e incluír la línea: <code>require File.expand_path(File.dirname(__FILE__) + '/helper_testcase')</code></li>
<li>utilizar el generador que incluye: <code>./script/generate helper_test Foo</code></li>
</ol>
<p>El test generado tendrá este aspecto:</p>
<pre><code class="ruby">   require File.dirname(__FILE__) + '/../../test_helper' </code><code class="ruby">   class FooHelperTest < HelperTestCase </code><code class="ruby">     include FooHelper </code><code class="ruby">     #fixtures :users, :articles </code><code class="ruby">     def setup       super     end </code><code class="ruby">   end </code></pre>
<p>A destacar que podemos utilizar <em>fixtures</em>.</p>
<p>Y la forma de proceder también es muy sencilla: creamos un test y en su interior podemos invocar al <em>helper</em> como si de un método más se tratara y comparar el resultado obtenido con los valores esperados. Si el <em>helper</em> tiene argumentos, ampliaremos el abanico de pruebas.</p>
<h3>Una pequeña reflexión</h3>
<p>La verdad es que no he podido pensar mucho sobre la efectividad de este <em>plugin</em> ni tampoco tengo experiencia utilizándolo (de hecho los desarrolladores de The-Shaker estábamos algo preocupados sobre el vacío que teníamos en los <em>helpers</em> de la aplicación, pues no tienen tests). En principio y echando un pequeño vistazo a los <em>helpers</em> que tenemos, parece que sí que se van a poder testear todos utilizando este <em>plugin</em>.</p>
<p>Sin embargo, hay que notar dos cosas:</p>
<p>La primera es que si en tu <em>helper</em> has utilizado una variable de instancia (confiando en que en la vista donde vas a utilizar dicho <em>helper</em>, la variable ya esté instanciada y con valor), debes de asignar una variable de igual nombre antes de invocar al helper en el test. Por ejemplo:</p>
<pre><code class="ruby"> def available_tabs   tabs =  "&lt;ul&gt;\n"   tabs << " &lt;li id=\"tab_blog\"&gt;" + link_to(_("Blog"), :controller =&gt; 'posts',            :action =&gt; 'index', :blog_nicetitle =&gt; @blog.nicetitle) + "&lt;/li&gt;\n"   tabs << "&lt;/ul&gt;\n" end</code></pre>
<p>Y el test:</p>
<pre><code class="ruby"> def test_avaible_tabs   @blog = blogs(:el_blog_de_quentin)   tabs = available_tabs   assert_equal tabs, '....' end</code></pre>
<p>Y la segunda es más bien una sugerencia: muchas veces los <em>helpers</em> generan HTML, y todos sabemos lo coñazo que puede ser comprobar la estructura del mismo, y las bondades del <a href="http://api.rubyonrails.com/classes/ActionController/Assertions/SelectorAssertions.html#M000208"><code>assert_select</code></a>. Pues bien, se puede hacer un <em>hack</em> no muy elegante, pero bastante práctico para poder utilizar <code>assert_select</code> con el valor obtenido por un <em>helper</em>. Basta con editar el fichero <code>helper_testcase.rb</code> e incluír la línea:</p>
<pre><code class="ruby">   @response   = ActionController::TestResponse.new </code></pre>
<p>dentro de la función <code>setup</code>. Y ahora, con que asignemos el <em>helper</em> a <code>@response.body</code> ya lo tenemos. Veamos un ejemplo:</p>
<pre><code class="ruby"> def test_avaible_tabs   @blog = blogs(:el_blog_de_quentin)   @response.body = available_tabs   assert_select 'ul' end</code></pre>
<p>Es sucio, poco semántico, y muy <abbr title="¿aún no sabes qué es esto?">DRY</abbr>, porque lo tienes que asignar tras cada invocación al <em>helper</em>, pero parece que de momento no hay otra forma. ¿Alguien se atreve a redefinir?
</p>
]]></content:encoded>
<comments>
http://www.inwebwetrust.net/post/2007/08/12/testeando-helpers#comentarios
</comments>
</item>

<item>
<title>Tests de unidad de ActionMailer</title>
<link>http://www.inwebwetrust.net/post/2007/08/12/tests-unidad-actionmailer</link>
<pubDate>2007-08-12T09:20:45+00:00</pubDate>
<category domain="http://www.inwebwetrust.net">Ruby on Rails</category>
<category domain="http://www.inwebwetrust.net">Testing</category>
<content:encoded><![CDATA[<p>ActionMailer es la librería incluída en Ruby on Rails para gestionar el envío de correos desde el framework.</p>
<p>Su <a href="http://wiki.rubyonrails.org/rails/pages/ActionMailer" title="http://wiki.rubyonrails.org/rails/pages/ActionMailer" id=link_0>uso</a> es bastante sencillo y cumple su labor perfectamente, a excepción de pequeños detalles que parece que falten por pulir.</p>
<p>Uno de esos "detalles insignificantes" es, para mi humilde opinión, el <em>testing</em>, que, aunque se puede realizar sin problemas, y con una cobertura muy buena de la funcionalidad, no queda tan limpio como queda en otras partes del <em>framework</em>.</p>
<p>De hecho, una de las cosas que más se echa en falta es algo de documentación. Por suerte, en los <a href="http://manuals.rubyonrails.com/">Manuales de Rails</a> (qué mal suena, ¿no?), encontramos un "libro" sobre <a href="http://manuals.rubyonrails.com/read/book/5">testing en Rails</a>, y uno de sus capítulos es <a href="http://manuals.rubyonrails.com/read/chapter/64">testing your Mailers</a>, que es justo lo que queremos hacer.</p>
<p>Ahí proponen un esquema o esqueleto para los tests de unidad tal que así:</p>
<pre><code class="ruby"> require File.dirname(__FILE__) + '/../test_helper' require 'my_mailer' </code> <code class="ruby"> class MyMailerTest < Test::Unit::TestCase   fixtures :users   FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures'   CHARSET = "utf-8"  </code><code class="ruby">   include ActionMailer::Quoting </code><code class="ruby">   def setup     ActionMailer::Base.delivery_method = :test     ActionMailer::Base.perform_deliveries = true     ActionMailer::Base.deliveries = [] </code><code class="ruby">     @expected = TMail::Mail.new     @expected.set_content_type "text", "plain", { "charset" => CHARSET }   end </code><code class="ruby">   def test_reset_password     user = User.find(:first)     newpass = 'newpass'     response = MyMailer.create_reset_password(user,newpass)     assert_equal 'Your New Password', response.subject     assert_match /Dear #{user.full_name},/, response.body     assert_match /New Password: #{newpass}/, response.body     assert_equal user.email, response.to[0]   end </code><code class="ruby">   private     def read_fixture(action)       IO.readlines("#{FIXTURES_PATH}/community_mailer/#{action}")     end </code><code class="ruby">     def encode(subject)       quoted_printable(subject, CHARSET)     end end </code></pre>
<p>Así un poco por encima, además de los requires pertinentes y de establecer unas cuantas constantes debemos de incluír <code class="ruby">include ActionMailer::Quoting</code> para poder utilizarlo en los tests con aquellos <em>emails</em> que tengan acentos, eñes o cualquier otro carácter no estándar en el <em>subject</em>.</p>
<p>En el método <code>setup</code> configuramos el <code>ActionMailer</code> y además creamos un objeto <code>TMail</code> llamado <code class="ruby">@expected</code>, y que utilizaremos en todos los tests para compararlo con el que genera nuestro modelo:</p>
<pre><code class="ruby">   def setup     ActionMailer::Base.delivery_method = :test     ActionMailer::Base.perform_deliveries = true     ActionMailer::Base.deliveries = [] </code><code class="ruby">     @expected = TMail::Mail.new     @expected.set_content_type "text", "plain", { "charset" => CHARSET }   end </code></pre>
<p>Y respecto a las <em>fixturas</em>, básicamente no tenemos, así que nos proponen utilizar ficheros de texto plano cuyo contenido será el contenido del <em>email</em>. Esos ficheros se sitúan en <code>RAIlS_ROOT/test/fixtures/community_mailer/</code> como se puede ver en la función <code>read_fixture</code>:</p>
<pre><code class="ruby">   def read_fixture(action)     IO.readlines("#{FIXTURES_PATH}/community_mailer/#{action}")   end </code></pre>
<h4>Nuestro propio test</h4>
<p>Con el esquema ya creado podemos empezar a escribir nuestros propios tests sobre nuestros modelos de <code>Mailer</code>.</p>
<p>Por ejemplo, veamos una acción muy simple de <a href="http://www.lacoctelera.com">La Coctelera</a>, que te envía un <em>email</em> cada vez que alguien te añade como amigo:</p>
<pre><code class="ruby"> 	def new_friend(user,friend)     @headers['reply-to'] = user.email     @from = 'admin@domain.com'     @recipients = friend.email     @subject = "[La Coctelera] #{user.shortname} te ha añadido como amigo"     @body = {       'user_name' => user.name,       'friend_name' => friend.name,       'profile_link' => profile_url(user.username),       'profile_link_friends' => friends_url(friend.username)     }   end </code></pre>
<p>Y esta es la vista asociada:</p>
<pre><code class="ruby"> Hola <%= @friend_name %>! </code><code class="ruby"> <%= @user_name %> te ha añadido como amig@. Puedes visitar su página en la siguiente dirección: <%= @profile_link %> </code><code class="ruby"> Puedes ver a todos tus amigos en: </code><code class="ruby"> <%= @profile_link_friends %> </code><code class="ruby"> Hasta otra! </code><code class="ruby"> -- La Coctelera http://www.lacoctelera.com </code></pre>
<p>El test podría ser algo tal que así:</p>
<pre><code class="ruby"> def test_new_friend   user = User.find_by_username('lucas')   friend = User.find_by_username('blat')   @expected.from = APP['adminmaster']   @expected.subject = encode("[La Coctelera] #{user.shortname} te ha añadido como amigo")   @expected.body = read_fixture('new_friend')   @expected.to = friend.email   @expected.reply_to = user.email   assert_equal @expected.encoded, Notifier.create_new_friend(user, friend).encoded end </code></pre>
<p>El procedimiento es muy sencillo:</p>
<ul>
<li>cargamos a los dos usuarios implicados en la acción</li>
<li>vamos rellenando los atributos de <code class="ruby">@expected</code> con los valores que esperamos que tenga el <em>email</em> resultante: remitente, asunto, contenido, destinatario...</li>
<li>finalmente, comparamos el <em>email</em> "esperado", con el que genera la acción <code>create_new_friend</code></li>
</ul>
<p>Hemos necesitado crear una <em>fixtura</em> <code>new_friend</code> con el siguiente contenido:</p>
<pre><code> Hola Fernando!  Lucas Nicolás te ha añadido como amig@. Puedes visitar su página en la siguiente dirección: http://test.host/lucas/perfil  Puedes ver a todos tus amigos en:  http://test.host/blat/amigos  Hasta otra!  -- La Coctelera http://test.host </code></pre>
<p>Como veis, esta <em>fixtura</em> tiene una limitación más que evidente: no es dinámica, y su contenido depende de los valores (en este caso de los usuarios), que estamos utilizando en el test.</p>
<p>También quiero destacar esta línea:</p>
<pre><code class="ruby">   @expected.subject = encode("[La Coctelera] #{user.shortname} te ha añadido como amigo") </code></pre>
<p>Cuando el <em>subject</em> del email vaya a incluir algún caracter acentuado, o con eñe, como es el caso, hay que forzar la recodificación de la cadena, pues <code>ActionMailer</code> también la recodificará cuando cree el <em>email</em>.</p>
<p>En un post posterior propondremos un par de mejoras para solventar alguna de las deficiencias que hemos visto.</p>
</%=></%=></%=></%=>]]></content:encoded>
<comments>
http://www.inwebwetrust.net/post/2007/08/12/tests-unidad-actionmailer#comentarios
</comments>
</item>

<item>
<title>Entendiendo la diferencia entre and y &amp;&amp;</title>
<link>http://www.inwebwetrust.net/post/2007/08/05/entendiendo-diferencia-entre-and-y-</link>
<pubDate>2007-08-05T22:43:11+00:00</pubDate>
<category domain="http://www.inwebwetrust.net">Ruby</category>
<content:encoded><![CDATA[<p>Para aquellos que nos preguntábamos por qué <code>&amp;&amp;</code> y <code>and</code> no son lo mismo, y porqué en el <a href="http://dev.rubyonrails.org/">Core de Rails prefieren <code>&amp;&amp;</code></a> aquí hay <a href="http://blog.jayfields.com/2007/08/ruby-operator-precedence-of-and-which.html">una buena explicación sobre cuál es su principal diferencia</a>, que no es más que un tema de precedencia de operadores.</p>
<p>Supongo que todo es acostumbrarse a utilizar uno u otro.</p>
]]></content:encoded>
<comments>
http://www.inwebwetrust.net/post/2007/08/05/entendiendo-diferencia-entre-and-y-#comentarios
</comments>
</item>
 
</channel>
</rss>
