Propiedades heredadas

2 views
Skip to first unread message

Choan Gálvez

unread,
May 31, 2008, 10:21:16 AM5/31/08
to nano...@googlegroups.com
Hola majos.

Otro caso de los de "molaría que..."

Molaría (o a mí me molaría) que algunas de las propiedades de las
páginas pudieran heredarse de su página madre (o abuela o etc).

Caso reciente: sitio bilingüe. La versión española cuelga de 'es/' y
la inglesa de 'en/'. Lo suyo sería definir la propiedad 'lang' en 'en/
en.yaml' y que todas sus hijas la heredaran.

En el momento en que lo necesité, salí del paso editando los yaml de
todo el árbol. Pero es un rollo.

Así que me he puesto a ver qué podía hacer, lo he hecho y os lo cuento
por si

a) os interesa o
b) se os ocurre una forma mejor de hacerlo.

Pasos: definimos en 'config.yaml' una propiedad 'inherited_props'.

# config.yaml
output_dir: "output"
data_source: "filesystem"
inherited_props:
- heredable
- lang

Metemos dentro del directorio 'lib/', en, digamos, 'page.rb' (el
nombre del fichero es irrelevante, lo importante es la extensión), el
siguiente código.

# lib/page.rb
module Nanoc
class Page

def attribute_named(name)
return @attributes[name] if @attributes.has_key?(name)
# la siguiente es la líne que añadimos, el resto es el método
original
return parent.attribute_named(name) if parent &&
@site.config[:inherited_props] &&
@site.config[:inherited_props].include?(name.to_s)
return @site.page_defaults[name] if @site.page_defaults.has_key?
(name)
return PAGE_DEFAULTS[name]
end

end

end

Y yastá.

Si en 'content.yaml' hemos definido 'heredable' como 'ouh yeah!',
cuando usemos `@page.heredable`, la propiedad se leerá

1. del yaml de la propia página o
2. del yaml del primer padre en el que se encuentre o
3. de los defaults del sitio (meta.yaml) o
4. de los defaults hardcoded en nanoc.

En fin, que me sirve, pero me quedo con la duda de si lo estoy
haciendo de forma adecuada.

¿Ideas?

Salud.
--
Choan Gálvez, que en un blog llamado Dizque cuenta lo que se le ocurre
<http://dizque.lacalabaza.net/>

Ale Muñoz

unread,
May 31, 2008, 4:00:13 PM5/31/08
to nano...@googlegroups.com
2008/5/31 Choan Gálvez <choan....@gmail.com>:

>
> En fin, que me sirve, pero me quedo con la duda de si lo estoy
> haciendo de forma adecuada.
>
> ¿Ideas?
>

Yo diría que la lógica es correcta correctísima, pero por una cuestión
de "future-proofing" yo haría algo asina:

# lib/page.rb
module Nanoc
class Page

alias :old_attribute_named :attribute_named
def attribute_named(name)
return old_attribute_named(name) unless old_attribute_named(name).nil?


# la siguiente es la líne que añadimos, el resto es el método original
return parent.attribute_named(name) if parent &&
@site.config[:inherited_props] &&
@site.config[:inherited_props].include?(name.to_s)

end
end
end

Básicamente lo que hace es crear un alias al método original
(old_attribute_named) en vez de reescribirlo (DRY :) para que el
plugin siga funcionando con futuras versiones de nanoc.

Gracias a Sergio Gil por hablar sobre los alias en su charla de
Metaprogramación de la Conferencia Rails 2007 :)

<http://2007.conferenciarails.org/archivos/sergio_gil_metaprogramacion.pdf>,
páginas 31 a 38.


--
Ale Muñoz
http://sofanaranja.com
http://bomberstudios.com

Choan Gálvez

unread,
May 31, 2008, 7:09:40 PM5/31/08
to nano...@googlegroups.com
Hola.

On 31/05/2008, at 22:00, Ale Muñoz wrote:

> Yo diría que la lógica es correcta correctísima, pero por una cuestión
> de "future-proofing" yo haría algo asina:
>
> # lib/page.rb
> module Nanoc
> class Page
> alias :old_attribute_named :attribute_named
> def attribute_named(name)
> return old_attribute_named(name) unless
> old_attribute_named(name).nil?
> # la siguiente es la líne que añadimos, el resto es el método
> original
> return parent.attribute_named(name) if parent &&
> @site.config[:inherited_props] &&
> @site.config[:inherited_props].include?(name.to_s)
> end
> end
> end
>
> Básicamente lo que hace es crear un alias al método original
> (old_attribute_named) en vez de reescribirlo (DRY :) para que el
> plugin siga funcionando con futuras versiones de nanoc.

Pero... ¿seguro que el resultado es el mismo?

El método `attribute_named` original también burbujea hacia arriba,
con la diferencia (respecto a mi propuesta) de que no considera los
valores de `parent`.

Y si juntamos esto con que una propiedad bien puede haberse
establecido a `nil` a mala leche... nos toparíamos con un caso raro.

Esto es, si tenemos

# config.yaml
inherited_props:
- foo

# content/content.yaml
foo: bar

# content/child/child.yaml
foo: ~

En tu versión, `@pages.find { |p| p.path == '/child/' }.foo`
devolvería "bar" y en la mía `nil`.

Elucubrado lo cual, voy a comprobar que es efectivamente así.

(Minutos después) Efectivamente, así es.

Seguro que se le puede dar otra vuelta (sobre todo en cuanto a la
definición de lo que quiero). Si se me ocurre algo os lo cuento.

Gracias por la nota sobre los alias.


> Gracias a Sergio Gil por hablar sobre los alias en su charla de
> Metaprogramación de la Conferencia Rails 2007 :)
>
> <http://2007.conferenciarails.org/archivos/sergio_gil_metaprogramacion.pdf
> >,
> páginas 31 a 38.


Coño, claro, por eso no ponía caras raras cuando hablaba de curryficar
funciones y cosas de esas raras.

Gracias mil y unas pocas más.
--
Choan Gálvez, que escribe sobre javascript en Scriptia
<http://blog.scriptia.net/>

Reply all
Reply to author
Forward
0 new messages