<?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>def Tenako.blog () end &#187; Uncategorized</title>
	<atom:link href="http://blog.tenako.com/category/uncategorized/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.tenako.com</link>
	<description></description>
	<lastBuildDate>Mon, 19 Jul 2010 17:32:02 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Rails: Carga dinamica de constantes</title>
		<link>http://blog.tenako.com/2008/11/14/rails-carga-dinamica-de-constantes/</link>
		<comments>http://blog.tenako.com/2008/11/14/rails-carga-dinamica-de-constantes/#comments</comments>
		<pubDate>Fri, 14 Nov 2008 21:09:24 +0000</pubDate>
		<dc:creator>farruco</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[dependencies rails constantes]]></category>

		<guid isPermaLink="false">http://blog.tenako.com/?p=41</guid>
		<description><![CDATA[Antes de empezar y por si alguien quiere, aquí tiene una brevísima intruducción a las constantes en Ruby
Vamos entonces con un  ejemplo sencillo en una consola de Ruby (sin el entorno de Rails cargado):

madtrick::ruby$ irb
irb&#40;main&#41;:001:0&#62; Constante
NameError: uninitialized constant Constante
        from &#40;irb&#41;:1
irb&#40;main&#41;:002:0&#62;

Como la constante no esta definida en [...]]]></description>
			<content:encoded><![CDATA[<p>Antes de empezar y por si alguien quiere, <a href="http://www.rubyist.net/~slagell/ruby/constants.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.rubyist.net');">aquí tiene una brevísima intruducción a las constantes en Ruby</a></p>
<p>Vamos entonces con un  ejemplo sencillo en una consola de Ruby (sin el entorno de Rails cargado):</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;">madtrick::ruby$ irb
irb<span style="color:#006600; font-weight:bold;">&#40;</span>main<span style="color:#006600; font-weight:bold;">&#41;</span>:001:0<span style="color:#006600; font-weight:bold;">&gt;</span> Constante
<span style="color:#CC00FF; font-weight:bold;">NameError</span>: uninitialized constant Constante
        from <span style="color:#006600; font-weight:bold;">&#40;</span>irb<span style="color:#006600; font-weight:bold;">&#41;</span>:<span style="color:#006666;">1</span>
irb<span style="color:#006600; font-weight:bold;">&#40;</span>main<span style="color:#006600; font-weight:bold;">&#41;</span>:002:0<span style="color:#006600; font-weight:bold;">&gt;</span></pre></div></div>

<p>Como la constante no esta definida en el contexto donde la reclamamos, se genera una excepción.</p>
<p>Pero si queremos, podemos capturar esta &#8220;referencia a una constante indefinida&#8221; dentro del contexto en el que nos encontramos, redefiniéndo el método <a href="http://apidock.com/ruby/Module/const_missing" onclick="javascript:pageTracker._trackPageview('/outbound/article/apidock.com');">const_missing </a> de Object:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;">irb<span style="color:#006600; font-weight:bold;">&#40;</span>main<span style="color:#006600; font-weight:bold;">&#41;</span>:010:0<span style="color:#006600; font-weight:bold;">&gt;</span> <span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#9966CC; font-weight:bold;">Module</span>
irb<span style="color:#006600; font-weight:bold;">&#40;</span>main<span style="color:#006600; font-weight:bold;">&#41;</span>:011:<span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&gt;</span> <span style="color:#9966CC; font-weight:bold;">def</span> const_missing<span style="color:#006600; font-weight:bold;">&#40;</span>name<span style="color:#006600; font-weight:bold;">&#41;</span>
irb<span style="color:#006600; font-weight:bold;">&#40;</span>main<span style="color:#006600; font-weight:bold;">&#41;</span>:012:<span style="color:#006666;">2</span><span style="color:#006600; font-weight:bold;">&gt;</span> <span style="color:#CC0066; font-weight:bold;">p</span> <span style="color:#996600;">&quot;Constante infenida: #{name}&quot;</span>
irb<span style="color:#006600; font-weight:bold;">&#40;</span>main<span style="color:#006600; font-weight:bold;">&#41;</span>:013:<span style="color:#006666;">2</span><span style="color:#006600; font-weight:bold;">&gt;</span> <span style="color:#9966CC; font-weight:bold;">end</span>
irb<span style="color:#006600; font-weight:bold;">&#40;</span>main<span style="color:#006600; font-weight:bold;">&#41;</span>:014:<span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&gt;</span> <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">nil</span>
irb<span style="color:#006600; font-weight:bold;">&#40;</span>main<span style="color:#006600; font-weight:bold;">&#41;</span>:015:0<span style="color:#006600; font-weight:bold;">&gt;</span> Constante
<span style="color:#996600;">&quot;Constante infenida: Constante&quot;</span>
<span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">nil</span></pre></div></div>

<p>Si queremos que la excepción continúe debemos de indicarlo con un raise al final del método:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;">irb<span style="color:#006600; font-weight:bold;">&#40;</span>main<span style="color:#006600; font-weight:bold;">&#41;</span>:016:0<span style="color:#006600; font-weight:bold;">&gt;</span> <span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#9966CC; font-weight:bold;">Module</span>
irb<span style="color:#006600; font-weight:bold;">&#40;</span>main<span style="color:#006600; font-weight:bold;">&#41;</span>:017:<span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&gt;</span> <span style="color:#9966CC; font-weight:bold;">def</span> const_missing<span style="color:#006600; font-weight:bold;">&#40;</span>name<span style="color:#006600; font-weight:bold;">&#41;</span>
irb<span style="color:#006600; font-weight:bold;">&#40;</span>main<span style="color:#006600; font-weight:bold;">&#41;</span>:018:<span style="color:#006666;">2</span><span style="color:#006600; font-weight:bold;">&gt;</span> <span style="color:#CC0066; font-weight:bold;">p</span> <span style="color:#996600;">&quot;Constante infenida: #{name}&quot;</span>
irb<span style="color:#006600; font-weight:bold;">&#40;</span>main<span style="color:#006600; font-weight:bold;">&#41;</span>:019:<span style="color:#006666;">2</span><span style="color:#006600; font-weight:bold;">&gt;</span> <span style="color:#CC0066; font-weight:bold;">raise</span>
irb<span style="color:#006600; font-weight:bold;">&#40;</span>main<span style="color:#006600; font-weight:bold;">&#41;</span>:020:<span style="color:#006666;">2</span><span style="color:#006600; font-weight:bold;">&gt;</span> <span style="color:#9966CC; font-weight:bold;">end</span>
irb<span style="color:#006600; font-weight:bold;">&#40;</span>main<span style="color:#006600; font-weight:bold;">&#41;</span>:021:<span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&gt;</span> <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">nil</span>
irb<span style="color:#006600; font-weight:bold;">&#40;</span>main<span style="color:#006600; font-weight:bold;">&#41;</span>:022:0<span style="color:#006600; font-weight:bold;">&gt;</span> Constante
<span style="color:#996600;">&quot;Constante infenida: Constante&quot;</span>
<span style="color:#CC00FF; font-weight:bold;">RuntimeError</span>: 
        from <span style="color:#006600; font-weight:bold;">&#40;</span>irb<span style="color:#006600; font-weight:bold;">&#41;</span>:<span style="color:#006666;">19</span>:<span style="color:#9966CC; font-weight:bold;">in</span> <span style="color:#996600;">`const_missing'
        from (irb):22
        from :0</span></pre></div></div>

<p><a href="http://www.rubyonrails.org/" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.rubyonrails.org');">Rails </a>, se aprovecha de esta funcionalidad para cargar dinámicamente constantes.¿Cómo?.Éso es lo que explicaremos a continuación:</p>
<p>Para seguir esta explicación de una manera mas cómoda, recomiendo tener a mano el fichero dependencies.rb incluido en <a href="http://as.rubyonrails.com/" onclick="javascript:pageTracker._trackPageview('/outbound/article/as.rubyonrails.com');">active-support</a>.</p>
<p><strong>1º.HOYGA NO HENCUENTRO LA CONSTANTE</strong></p>
<p>Rails , al igual que hicimos nosotros antes , abre las clases Module y Class para redefinir el método const_missing.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#9966CC; font-weight:bold;">Module</span> <span style="color:#008000; font-style:italic;">#:nodoc:</span>
  ...
  <span style="color:#008000; font-style:italic;"># Use const_missing to autoload associations so we don't have to</span>
  <span style="color:#008000; font-style:italic;"># require_association when using single-table inheritance.</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> const_missing<span style="color:#006600; font-weight:bold;">&#40;</span>class_id<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#6666ff; font-weight:bold;">ActiveSupport::Dependencies</span>.<span style="color:#9900CC;">load_missing_constant</span> <span style="color:#0000FF; font-weight:bold;">self</span>, class_id
  <span style="color:#9966CC; font-weight:bold;">end</span>
...
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#9966CC; font-weight:bold;">Class</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> const_missing<span style="color:#006600; font-weight:bold;">&#40;</span>const_name<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#CC00FF; font-weight:bold;">Object</span>, <span style="color:#CC00FF; font-weight:bold;">Kernel</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9966CC; font-weight:bold;">include</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">self</span><span style="color:#006600; font-weight:bold;">&#41;</span> || parent ==
      <span style="color:#9966CC; font-weight:bold;">super</span>
    <span style="color:#9966CC; font-weight:bold;">else</span>
      <span style="color:#9966CC; font-weight:bold;">begin</span>
        <span style="color:#9966CC; font-weight:bold;">begin</span>
          <span style="color:#6666ff; font-weight:bold;">ActiveSupport::Dependencies</span>.<span style="color:#9900CC;">load_missing_constant</span> <span style="color:#0000FF; font-weight:bold;">self</span>, const_name
        <span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#CC00FF; font-weight:bold;">NameError</span>
          parent.<span style="color:#9900CC;">send</span> <span style="color:#ff3333; font-weight:bold;">:const_missing</span>, const_name
        <span style="color:#9966CC; font-weight:bold;">end</span>
      <span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#CC00FF; font-weight:bold;">NameError</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> e
        <span style="color:#008000; font-style:italic;"># Make sure that the name we are missing is the one that caused the error</span>
        parent_qualified_name = <span style="color:#6666ff; font-weight:bold;">ActiveSupport::Dependencies</span>.<span style="color:#9900CC;">qualified_name_for</span> parent, const_name
        <span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#9966CC; font-weight:bold;">unless</span> e.<span style="color:#9900CC;">missing_name</span>? parent_qualified_name
        qualified_name = <span style="color:#6666ff; font-weight:bold;">ActiveSupport::Dependencies</span>.<span style="color:#9900CC;">qualified_name_for</span> <span style="color:#0000FF; font-weight:bold;">self</span>, const_name
        <span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#CC00FF; font-weight:bold;">NameError</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;uninitialized constant #{qualified_name}&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">copy_blame</span>!<span style="color:#006600; font-weight:bold;">&#40;</span>e<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>No entiendo porque en el método const_missing redefinido en Class comprobamos si self es Kernel ya que Kernel es un Module y por tanto nunca invocaria al const_missing de una clase.<br />
Pero ambas &#8220;redefiniciones&#8221; nos llevan al mismo punto: <strong>ActiveSupport::Dependencies.load_missing_constant</strong></p>
<p><strong>2º.Carguémos la constante</strong></p>
<p>Una vez dentro de load_missing_constant lo primero que se lleva a cabo es una comprobacion para determinar si el modulo o clase que desea cargar la constante es Kernel para en caso afirmativo intercambiar este por Object, si Object no tiene definida la constante deseada o devolver el valor de la constante en caso contrario.Esto tiene sentido ya que Kernel es un mixin de Object y por tanto sus constantes lo serán a la vez de Object.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">if</span> from_mod == <span style="color:#CC00FF; font-weight:bold;">Kernel</span>
        <span style="color:#9966CC; font-weight:bold;">if</span> ::<span style="color:#CC00FF; font-weight:bold;">Object</span>.<span style="color:#9900CC;">const_defined</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>const_name<span style="color:#006600; font-weight:bold;">&#41;</span>
          log <span style="color:#996600;">&quot;Returning Object::#{const_name} for Kernel::#{const_name}&quot;</span>
          <span style="color:#0000FF; font-weight:bold;">return</span> ::<span style="color:#CC00FF; font-weight:bold;">Object</span>.<span style="color:#9900CC;">const_get</span><span style="color:#006600; font-weight:bold;">&#40;</span>const_name<span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#9966CC; font-weight:bold;">else</span>
          log <span style="color:#996600;">&quot;Substituting Object for Kernel&quot;</span>
          from_mod = <span style="color:#CC00FF; font-weight:bold;">Object</span>
        <span style="color:#9966CC; font-weight:bold;">end</span>
      <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>En caso de no encontrarse dicha constante en Object pasamos a lo siguiente:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;">from_mod = <span style="color:#CC00FF; font-weight:bold;">Object</span> <span style="color:#9966CC; font-weight:bold;">if</span> from_mod.<span style="color:#9900CC;">name</span>.<span style="color:#9900CC;">blank</span>?
&nbsp;
      <span style="color:#9966CC; font-weight:bold;">unless</span> qualified_const_defined?<span style="color:#006600; font-weight:bold;">&#40;</span>from_mod.<span style="color:#9900CC;">name</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&amp;&amp;</span> from_mod.<span style="color:#9900CC;">name</span>.<span style="color:#9900CC;">constantize</span>.<span style="color:#9900CC;">object_id</span> == from_mod.<span style="color:#9900CC;">object_id</span>
        <span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#CC00FF; font-weight:bold;">ArgumentError</span>, <span style="color:#996600;">&quot;A copy of #{from_mod} has been removed from the module tree but is still active!&quot;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Con lo que comprobamos:</p>
<ul>
<li>Si estamos ante un <a href="http://ruby-doc.org/core/classes/Module.html#M001705" onclick="javascript:pageTracker._trackPageview('/outbound/article/ruby-doc.org');">modulo anónimo</a></li>
<li>La segunda parte no me queda muy claro cuando se puede dar</li>
</ul>
<p>En la siguiente linea de código, se me plantea otra nueva duda</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#CC00FF; font-weight:bold;">ArgumentError</span>, <span style="color:#996600;">&quot;#{from_mod} is not missing constant #{const_name}!&quot;</span> <span style="color:#9966CC; font-weight:bold;">if</span> uninherited_const_defined?<span style="color:#006600; font-weight:bold;">&#40;</span>from_mod, const_name<span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>Si estamos buscando una constante (const_name) no definida en from_mod, ¿Por qué uninherited_const_defined?(from_mod,const_name) habría de devolver true? Uninherited_const_defined? es como sigue:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#9966CC; font-weight:bold;">Module</span>.<span style="color:#9900CC;">method</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:const_defined</span>?<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">arity</span> == <span style="color:#006666;">1</span>
      <span style="color:#008000; font-style:italic;"># Does this module define this constant?</span>
      <span style="color:#008000; font-style:italic;"># Wrapper to accomodate changing Module#const_defined? in Ruby 1.9</span>
      <span style="color:#9966CC; font-weight:bold;">def</span> uninherited_const_defined?<span style="color:#006600; font-weight:bold;">&#40;</span>mod, const<span style="color:#006600; font-weight:bold;">&#41;</span>
        mod.<span style="color:#9900CC;">const_defined</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>const<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">else</span>
      <span style="color:#9966CC; font-weight:bold;">def</span> uninherited_const_defined?<span style="color:#006600; font-weight:bold;">&#40;</span>mod, const<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#008000; font-style:italic;">#:nodoc:</span>
        mod.<span style="color:#9900CC;">const_defined</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>const, <span style="color:#0000FF; font-weight:bold;">false</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Dependiendo de la versión de Ruby ( 1.9 o inferior) utilizara un método un otro con mismo resultado: invocar <a href="http://apidock.com/ruby/Module/const_defined%3F" onclick="javascript:pageTracker._trackPageview('/outbound/article/apidock.com');">const_defined?</a> sobre el módulo.Y esto es lo que no entiendo, si const_name genero un const_missing en dicho modulo, porque ahora no habría de hacerlo&#8230;.</p>
<p>En fin, sigamos.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;">qualified_name = qualified_name_for from_mod, const_name
path_suffix = qualified_name.<span style="color:#9900CC;">underscore</span>
name_error = <span style="color:#CC00FF; font-weight:bold;">NameError</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;uninitialized constant #{qualified_name}&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p><strong>qualified_name_for</strong> devuelve el nombre cualificado para el modulo y constante dados</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># Return the constant path for the provided parent and constant name.</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> qualified_name_for<span style="color:#006600; font-weight:bold;">&#40;</span>mod, name<span style="color:#006600; font-weight:bold;">&#41;</span>
      mod_name = to_constant_name mod
      <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">%</span>w<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">Object</span> <span style="color:#CC00FF; font-weight:bold;">Kernel</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9966CC; font-weight:bold;">include</span>? mod_name<span style="color:#006600; font-weight:bold;">&#41;</span> ? name.<span style="color:#9900CC;">to_s</span> : <span style="color:#996600;">&quot;#{mod_name}::#{name}&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Ejemplos:</p>
<ul>
<li>Para mod A y name C , tendriamos A::C</li>
<li>Para mod A::C y name D, tendriamos A::C::D</li>
<li>Para mod Object (o Kernel) y name C, tendriamos C</li>
</ul>
<p><strong><br />
path_suffix = qualified_name.underscore</strong>.De esta linea obtendremos lo siguiente, ejemplos:</p>
<ul>
<li>Para qualified_name A::C , tendremos a/c</li>
<li>
Para qualified_name A::B::C, tendremos a/b/c</li>
<li>Para qualified_name A, tendremos a</li>
</ul>
<p>Y por ultimo <strong>name_error = NameError.new</strong> prepara un objeto de clase NameError para el caso de que no podamos hacer nada por cargar la constante.</p>
<p><strong>3º.¿Pero cargamos la constante o no?</strong></p>
<p>Hasta ahora no hemos realizado ningún intento por cargar la constante perdida (buen titulo para una peli&#8230;Las aventuras de la constante perdida), pero a partir de ahora es cuando empieza lo divertido.</p>
<p>Para empezar intentamos buscar un directorio en nuestro load_path (definido en Dependencies.load_paths) que albergue una ruta igual a path_suffix (indicamos como se determina dicho path_suffix, lineas mas arriba) con terminación &#8220;.rb&#8221;.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;">file_path = search_for_file<span style="color:#006600; font-weight:bold;">&#40;</span>path_suffix<span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>Es decir, si nuestro path_suffix es &#8220;a/b/c.rb&#8221;, buscamos algún path de entre los que tenemos disponibles para cargar ficheros que contenga la ruta &#8220;a/b/c.rb&#8221;.Ejemplo:</p>
<p>Si nuestro load_path esta formado por:</p>
<ul>
<li>/home/lib/funny_lib, la ruta completa seria /home/lib/funny_lib/a/b/c.rb</li>
<li>/home/lib/dll_hell, la ruta completa seria /home/lib/dll_hell/a/b/c.rb</li>
<li>/home/lib/act_as_pr0n, la ruta completa seria /home/lib/act_as_pr0n/a/b/c.rb</li>
</ul>
<p>El primero de los anteriores que exista será el valor devuelto por search_for_file o nil en caso que ninguno de ellos exista.</p>
<p>Lo siguiente que nos encontramos es una gran estructura condicional</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;">      <span style="color:#9966CC; font-weight:bold;">if</span> file_path <span style="color:#006600; font-weight:bold;">&amp;&amp;</span> ! loaded.<span style="color:#9966CC; font-weight:bold;">include</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">expand_path</span><span style="color:#006600; font-weight:bold;">&#40;</span>file_path<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#008000; font-style:italic;"># We found a matching file to load</span>
        require_or_load file_path
        <span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#CC00FF; font-weight:bold;">LoadError</span>, <span style="color:#996600;">&quot;Expected #{file_path} to define #{qualified_name}&quot;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> uninherited_const_defined?<span style="color:#006600; font-weight:bold;">&#40;</span>from_mod, const_name<span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#0000FF; font-weight:bold;">return</span> from_mod.<span style="color:#9900CC;">const_get</span><span style="color:#006600; font-weight:bold;">&#40;</span>const_name<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">elsif</span> mod = autoload_module!<span style="color:#006600; font-weight:bold;">&#40;</span>from_mod, const_name, qualified_name, path_suffix<span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#0000FF; font-weight:bold;">return</span> mod
      <span style="color:#9966CC; font-weight:bold;">elsif</span> <span style="color:#006600; font-weight:bold;">&#40;</span>parent = from_mod.<span style="color:#9900CC;">parent</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&amp;&amp;</span> parent != from_mod <span style="color:#006600; font-weight:bold;">&amp;&amp;</span>
            ! from_mod.<span style="color:#9900CC;">parents</span>.<span style="color:#9900CC;">any</span>? <span style="color:#006600; font-weight:bold;">&#123;</span> |p| uninherited_const_defined?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC0066; font-weight:bold;">p</span>, const_name<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
        <span style="color:#008000; font-style:italic;"># If our parents do not have a constant named +const_name+ then we are free</span>
        <span style="color:#008000; font-style:italic;"># to attempt to load upwards. If they do have such a constant, then this</span>
        <span style="color:#008000; font-style:italic;"># const_missing must be due to from_mod::const_name, which should not</span>
        <span style="color:#008000; font-style:italic;"># return constants from from_mod's parents.</span>
        <span style="color:#9966CC; font-weight:bold;">begin</span>
          <span style="color:#0000FF; font-weight:bold;">return</span> parent.<span style="color:#9900CC;">const_missing</span><span style="color:#006600; font-weight:bold;">&#40;</span>const_name<span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#CC00FF; font-weight:bold;">NameError</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> e
          <span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#9966CC; font-weight:bold;">unless</span> e.<span style="color:#9900CC;">missing_name</span>? qualified_name_for<span style="color:#006600; font-weight:bold;">&#40;</span>parent, const_name<span style="color:#006600; font-weight:bold;">&#41;</span>
          <span style="color:#CC0066; font-weight:bold;">raise</span> name_error
        <span style="color:#9966CC; font-weight:bold;">end</span>
      <span style="color:#9966CC; font-weight:bold;">else</span>
        <span style="color:#CC0066; font-weight:bold;">raise</span> name_error
      <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Vayamos por partes</p>
<p><strong>3.1 Cargando la constante desde un fichero</strong></p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">if</span> file_path <span style="color:#006600; font-weight:bold;">&amp;&amp;</span> ! loaded.<span style="color:#9966CC; font-weight:bold;">include</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">expand_path</span><span style="color:#006600; font-weight:bold;">&#40;</span>file_path<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#008000; font-style:italic;"># We found a matching file to load</span>
        require_or_load file_path
        <span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#CC00FF; font-weight:bold;">LoadError</span>, <span style="color:#996600;">&quot;Expected #{file_path} to define #{qualified_name}&quot;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> uninherited_const_defined?<span style="color:#006600; font-weight:bold;">&#40;</span>from_mod, const_name<span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#0000FF; font-weight:bold;">return</span> from_mod.<span style="color:#9900CC;">const_get</span><span style="color:#006600; font-weight:bold;">&#40;</span>const_name<span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>Si se da que tenemos un file_path, y este no esta cargado actualmente, lo cargamos mediante require_or_load.Este método necesita para el solo otra entrada en el blog de lo amplio que es.</p>
<p>Aquí podemos apreciar por tanto otra convención de Rails.Es decir, si por ejemplo tenemos un plugin que añade una constante a ActiveRecord (sea la constante Constant) y queremos que Rails cargue automáticamente esta constante sin tener que indicarlo nosotros explícitamente mediante un require, debemos de:</p>
<ul>
<li>En el directorio /lib de nuestro plugin crear otro que se llame active_record</li>
<li>Dentro de este ultimo directorio crear un fichero que se llame constant.rb</li>
</ul>
<p>Si no cumplimos dicha convencion, tras cargar el fichero podemos obtener el siguiente error</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#CC00FF; font-weight:bold;">LoadError</span>, <span style="color:#996600;">&quot;Expected #{file_path} to define #{qualified_name}&quot;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> uninherited_const_defined?<span style="color:#006600; font-weight:bold;">&#40;</span>from_mod, const_name<span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>Hay que tener cuidado con este método ya que como se indico anteriormente, el file_path elegido sera el primero que exista, es decir que si hay dos plugins con la misma estructura y en ninguno de ellos requerimos explícitamente el fichero donde se define la constante el primero en ser elegido ocultara la presencia del otro.</p>
<p>3.2</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">elsif</span> mod = autoload_module!<span style="color:#006600; font-weight:bold;">&#40;</span>from_mod, const_name, qualified_name, path_suffix<span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#0000FF; font-weight:bold;">return</span> mod</pre></div></div>

<p>con autoload_module! como sigue,</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># Attempt to autoload the provided module name by searching for a directory</span>
<span style="color:#008000; font-style:italic;"># matching the expect path suffix. If found, the module is created and assigned</span>
<span style="color:#008000; font-style:italic;"># to +into+'s constants with the name +const_name+. Provided that the directory</span>
<span style="color:#008000; font-style:italic;"># was loaded from a reloadable base path, it is added to the set of constants</span>
<span style="color:#008000; font-style:italic;"># that are to be unloaded.</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> autoload_module!<span style="color:#006600; font-weight:bold;">&#40;</span>into, const_name, qualified_name, path_suffix<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0000FF; font-weight:bold;">return</span> <span style="color:#0000FF; font-weight:bold;">nil</span> <span style="color:#9966CC; font-weight:bold;">unless</span> base_path = autoloadable_module?<span style="color:#006600; font-weight:bold;">&#40;</span>path_suffix<span style="color:#006600; font-weight:bold;">&#41;</span>
      mod = <span style="color:#9966CC; font-weight:bold;">Module</span>.<span style="color:#9900CC;">new</span>
      into.<span style="color:#9900CC;">const_set</span> const_name, mod
      autoloaded_constants <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> qualified_name <span style="color:#9966CC; font-weight:bold;">unless</span> load_once_paths.<span style="color:#9966CC; font-weight:bold;">include</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>base_path<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0000FF; font-weight:bold;">return</span> mod
    <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Como bien indica el comentario, autoload_module! primero determina mediante autoloadable_module? si existe un path de entre los disponibles en nuestro load_path al cual añadiéndole el path_suffix, exista como directorio.Si es así, continuamos, sino devolvemos nil.</p>
<p>Si existe dicho path, creamos un modulo anónimo y añadimos la constante que falta a from_mod con el valor de este modulo anónimo.<br />
Para terminar en autoload_module!, incluimos la constante cualificada en Dependencies.autoloaded_constants a menos que el directorio sea un directorio que solo se puede cargar una vez durante la ejecución de Rails (definidos en Dependencies.load_once_paths).</p>
<p><strong>3.3 Ni fichero, ni directorio.¿Dónde coj***s esta la constante?</strong></p>
<p>Llegados a este punto es porque ningún load_path de los disponibles alberga o bien un directorio o bien un fichero que siga la estructura designada por path_suffix.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">elsif</span> <span style="color:#006600; font-weight:bold;">&#40;</span>parent = from_mod.<span style="color:#9900CC;">parent</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&amp;&amp;</span> parent != from_mod <span style="color:#006600; font-weight:bold;">&amp;&amp;</span>
            ! from_mod.<span style="color:#9900CC;">parents</span>.<span style="color:#9900CC;">any</span>? <span style="color:#006600; font-weight:bold;">&#123;</span> |p| uninherited_const_defined?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC0066; font-weight:bold;">p</span>, const_name<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
        <span style="color:#008000; font-style:italic;"># If our parents do not have a constant named +const_name+ then we are free</span>
        <span style="color:#008000; font-style:italic;"># to attempt to load upwards. If they do have such a constant, then this</span>
        <span style="color:#008000; font-style:italic;"># const_missing must be due to from_mod::const_name, which should not</span>
        <span style="color:#008000; font-style:italic;"># return constants from from_mod's parents.</span>
        <span style="color:#9966CC; font-weight:bold;">begin</span>
          <span style="color:#0000FF; font-weight:bold;">return</span> parent.<span style="color:#9900CC;">const_missing</span><span style="color:#006600; font-weight:bold;">&#40;</span>const_name<span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#CC00FF; font-weight:bold;">NameError</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> e
          <span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#9966CC; font-weight:bold;">unless</span> e.<span style="color:#9900CC;">missing_name</span>? qualified_name_for<span style="color:#006600; font-weight:bold;">&#40;</span>parent, const_name<span style="color:#006600; font-weight:bold;">&#41;</span>
          <span style="color:#CC0066; font-weight:bold;">raise</span> name_error
        <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Resumiendo que esto se alarga demasiado&#8230;.en este ultimo bloque, buscaremos la constante en los padres de from_mod.La explicacion a como se obtienen los padres para un path dado es la siguiente:</p>
<blockquote><p>
En introspection.rb:</p>
<p># Returns all the parents of this module according to its name, ordered from<br />
  # nested outwards. The receiver is not contained within the result.<br />
  #<br />
  #   module M<br />
  #     module N<br />
  #     end<br />
  #   end<br />
  #   X = M::N<br />
  #<br />
  #   p M.parents    # => [Object]<br />
  #   p M::N.parents # => [M, Object]<br />
  #   p X.parents    # => [M, Object]<br />
  #
</p></blockquote>
<p> y si tampoco esta definida en ninguno de sus padres, invocaremos denuevo todo el proceso desde el principio sobre el padre de from_mod</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#0000FF; font-weight:bold;">return</span> parent.<span style="color:#9900CC;">const_missing</span><span style="color:#006600; font-weight:bold;">&#40;</span>const_name<span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>Mencionar que si no encontramos la constante en ningun sitio se lanzara la excepcion de clase NameError creada anteriormente.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.tenako.com/2008/11/14/rails-carga-dinamica-de-constantes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
