Forum: Rails-ES [Off-topic] Como funciona el [include]

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Adce10d7f1dbabcdab8f525a59cec32f?d=identicon&s=25 Andrés Gutiérrez (andresgutgon)
on 2009-01-14 15:49
(Received via mailing list)
Hola a todos, veréis, estoy siguiendo un tutorial de ruby  a pelo, nada
de
rails. Pero voy a hacer la consulta aqui por tres motivos:
1-es una pregunta super rápida.
2-Es de interés para la gente que esta empezando con Rails (creo).
3-Esta es la única lista a la que estoy apuntado sobre (ruby, rails). De
momento. Si me surgen muchas dudas de puro ruby, prometo apuntarme a la
lista de Ruby

Bueno, al grano, que seguro que es una chorrada.
Estoy leyendo sobre la seudo-herencia multiple en ruby, y me he topado
con
los mixins (modulos)
La pregunta:
Cuando yo incluyo un modulo en mi clase asi :

module Movement
  def run
    puts "I'm running!"
  end
  def walk
    puts "I'm walking a bit briskly!"
  end
  def crawl
    puts "I'm so slowwww!"
  end
end
------------------------------------
class Man
  include Movement
  def jump
    puts "I'm bipedal and I can jump like a fool!"
  end
end


¿Como sabe mi clase donde encontrar al modulo [Movement ]? ¿O donde he
de
poner el modulo [Movement ] para que mi clase lo encuentre?
Me refiero a Ruby en general, no a una App rails, aunque si me decis
como se
hace en Rails también perfecto

Saludos
6f952bee7570a3db2ecba5b06c0062b3?d=identicon&s=25 Fernando Guillen (fguillen)
on 2009-01-14 15:57
(Received via mailing list)
Quizás la disertación de guillermo te ayude a comprender algo:

http://cientifico.net/post/2008/12/30/diferencia-e...

Saludos
f.

El día 14 de enero de 2009 15:49, Andrés gutiérrez
<andresgutgon@gmail.com>
escribió:> Hola a todos, veréis, estoy siguiendo un tutorial de ruby  a pelo, 
nada de
Ba6e83f1628194a060613026a33d8881?d=identicon&s=25 Isaac Feliu Pérez (Guest)
on 2009-01-14 15:58
(Received via mailing list)
Andrés,

Rails añade toda una magia de auto-load de ficheros que engaña un
poco, ya que no es como funciona ruby realmente.

Básicamente rails se apaña con el método const_missing de la classe
Object, de forma que cuando llamas a una constante [Movement] que no
existe, busca en todo el load_path un fichero llamado movement.rb y le
hace un require. (Explicado a grosso modo).

En el caso concreto de rails, se trata de poner el fichero movement.rb
en un directorio que esté en el load_path de rails, ya sea en /lib, o
en /app/models /app/controllers, etc...

En el caso de rails puro, debes hacer un require manual del fichero
movement.rb antes de poder declarar el include, o ruby te dará un
error indicándote que no existe la constante Moevement.

Espero haber aclarado algo tus dudas, para mirar el tema del
const_missing, te passo la url a la
documentación:
http://www.ruby-doc.org/core/classes/Module.html#M001716

Saludos,
--
Isaac Feliu
Adce10d7f1dbabcdab8f525a59cec32f?d=identicon&s=25 Andrés Gutiérrez (andresgutgon)
on 2009-01-14 16:25
(Received via mailing list)
Gracias a  los dos, en un par de horas me pondre con el tema y me mirare
detenidamente vuestros enlaces. Gracias por el interes.

El 14 de enero de 2009 15:57, Isaac Feliu Pérez
<isaac.feliu@gmail.com>escribió:
7223c62b7310e164eb79c740188abbda?d=identicon&s=25 Xavier Noria (fxn)
on 2009-01-14 16:38
(Received via mailing list)
2009/1/14 Andrés gutiérrez <andresgutgon@gmail.com>:

> ¿Como sabe mi clase donde encontrar al modulo [Movement ]? ¿O donde he de
> poner el modulo [Movement ] para que mi clase lo encuentre?
> Me refiero a Ruby en general, no a una App rails, aunque si me decis como se
> hace en Rails también perfecto

Ruby no lo sabe.

El modulo Movement ha de estar definido en un fichero del cual hay que
hacer un require en algun punto de la aplicacion.

En cuanto al nombre del fichero lo tienes que saber tu (que eres quien
hace el require) y es arbitrario. Un .rb puede tecnicamente definir
tantas clases o modulos como quiera (incluidos ninguno :-). Si
Movement esta definido en foo.rb, como efecto secundario de
interpretar

   require "foo"

quedara Movement definido (para completar la ronda, Movement
tecnicamente es una constante normal y corriente que almacena un
objeto de tipo Module).

Ruby busca esos ficheros en un path que queda definido hard-coded en
tiempo de compilacion, que puedes consultar en la variable $:.

$ irb
irb(main):001:0> $:
=> ["/Users/fxn/prj/mizuho/lib", "/opt/local/lib/ruby/site_ruby/1.8",
"/opt/local/lib/ruby/site_ruby/1.8/i686-darwin9",
"/opt/local/lib/ruby/site_ruby",
"/opt/local/lib/ruby/vendor_ruby/1.8",
"/opt/local/lib/ruby/vendor_ruby/1.8/i686-darwin9",
"/opt/local/lib/ruby/vendor_ruby", "/opt/local/lib/ruby/1.8",
"/opt/local/lib/ruby/1.8/i686-darwin9", "."]

Se puede extender con la variable de entorno RUBYLIB, o bien
modificando $: a pelómetro (es un array de cadenas), y tambien en
linea de comandos con la opcion -I.
Adce10d7f1dbabcdab8f525a59cec32f?d=identicon&s=25 Andrés Gutiérrez (andresgutgon)
on 2009-01-14 21:47
(Received via mailing list)
def Object.const_missing(name)
    @looked_for ||= {}
    str_name = name.to_s
    raise "Class not found: #{name}" if @looked_for[str_name]
    @looked_for[str_name] = 1
    file = str_name.downcase
    require file
    klass = const_get(name)
    return klass if klass
    raise "Class not found: #{name}"
  end
Vale Isaac, me he mirado el metodo  const_missing(name), que es como
lo hace rails no?
A ver, con mis propias palabras diria "rails usa const_missing(name)
para busar la constante que yo paso a mi clase al hacer: include
Mimodulo"
Pregunta:
Cuando hago un include, el modulo que estoy llamando lo busca en el
archivo del mismo nombre en minusculas en el load_path que tiene
definido rails?
Como dice en la document. cuando yo llamo al modulo con include, ruby
llama al metodo append_features
<http://www.ruby-doc.org/core/classes/Module.html#M001659> y este
metodo carga todos los: ( the constants
<http://www.ruby-doc.org/core/classes/Module.html#M001679>, methods,
and module variables of
this module ) Y en este momento es cuando rails llama a
const_missing????para saber si el modulo esta en el load_path?

Como ves no tengo el camino claro, pero sigo mirando, a ver si soy
capaz de explicarlo y explicarmelo claramente.

Esto de arriba muestra lo confuso que tengo de momento la vision
general de lo que es el funcionamiento del include. Pero volviendo al
codigo de arriba El const_missing, hay cosas que no entiendo en el
codigo
 @looked_for ||= {}. Esto es un operado de ruby que es equivalente a
esto p.ej.:
if not @looked_for
  @looked_for = {}
end
Es esto correcto, la variable @looked_for se asigna a un hash vacio si
no esta definida?????

Y esto:
raise "Class not found: #{name}" if @looked_for[str_name]
Se produce un error si el name que se le pasa a const_missing no esta
en la variable @looked_for????
Esto si que no veo por donde  me da el aire....

@looked_for[str_name] = 1 Por que se le asigna valor 1???
klass = const_get(name) esto lo que hace es retornar el valor de NAME.

return klass if klass.  ESTO QUE??? retorna la Klass si la Klass que
(if Klass)??? ¿Que tiene que pasar para que la retorne?
Bueno, no os agobies con mis preguntas, que sólo expongo todas mis
dudas juntas, para que escojais alguna :-) si os apetece y me voy
aclarando una por una
Gracias,

NOTA:
Si hay premio para el mensaje peor redactado y confuso del 2009,
seguro que lo gano. Espero ir aclarando el hilo para que quede
legible, pero ahora mismo esta confuso y es tarde y mi cabeza,...

Bueno, gracias de nuevo

El 14 de enero de 2009 16:38, Xavier Noria <fxn@hashref.com> escribió:

2009/1/14 Andrés gutiérrez <andresgutgon@gmail.com>:
Adce10d7f1dbabcdab8f525a59cec32f?d=identicon&s=25 Andrés Gutiérrez (andresgutgon)
on 2009-01-14 22:12
(Received via mailing list)
Vale!!!!

Una cosa clara. Según lo que me ha dicho Xavier (+-)
#man.rb
----------------------------------------------------------
class Man
     require "fightervalues"
  include FighterValues
  def jump
    puts "I'm bipedal and I can jump like a fool!"
  end
end
----------------------------------------------------------

mister_man = Man.new
mister_man.run

Esto funciona porque tengo un archivo "fightervalues.rb" en el mismo
directorio que "man.rb".  Con el requiere no hace falta poner la
extensión(.rb). ¿NO?, en PHP me parece que SI.

Ahora para hacerlo un poco más centralizado y si es posible al estilo
rails,
es decir. Yo estoy siguiendo un tutorial en el que voy haciendo
minicodigo
como "man.rb"
Si me quiero crear modulos que luego pueda usar para estos archivos y
que
todos estos modulos esten en un unico directorio "lib". Como lo hago???

Y como lo hago para hacerlo al estilo rails, es decir sin que me haga
falta
hacer el requiere en todas las clases-archivos-ejemplos que haga y en
las
que quiera usar los modulos que tengo en "lib"

Xavier, creo que estas preguntas ya me las has respondido, era lo de:
>>Se puede extender con la variable de entorno RUBYLIB, o bien
>>modificando $: a pelómetro (es un array de cadenas), y tambien en
>>linea de comandos con la opcion -I.

Pero es que no me aclaro con el tema de modificar PATH's. Es algo que no
me
entra en la cabeza, y ademas me falta base(comandos) para funcionar con
el
terminal

Bueno, en resumen, lo que ahora me funciona es mas o menos como funciono
en
PHP(cutre y sin OOP). Incluyo archivos y gracias a eso me sirvo de sus
constantes, variables y funciones.
En ruby por lo que veo, para aprovecharme de lo que tengo en
"fightervalues.rb" debo poner: [include FighterValues], de lo contrario
me
salta este error:
man.rb:9: undefined method `run' for #<Man:0x29220> (NoMethodError)

Lo tengo requiereADO, pero NO includeADO asi que Class man no pilla los
metodos de module FighterValues. Si vuelvo a poner el include, ya me
puedo
volver a aprovechar de los metodos de FighterValues

El 14 de enero de 2009 21:46, Andrés gutiérrez
<andresgutgon@gmail.com>escribió:
Adce10d7f1dbabcdab8f525a59cec32f?d=identicon&s=25 Andrés Gutiérrez (andresgutgon)
on 2009-01-14 22:46
(Received via mailing list)
Perdón por ser tan pesado, prometo que por hoy lo dejo, solo una cosa.
Googleando he visto que este tio [1], ha puesto una script en su
directorio
/public con lo siguiente:

#!/bin/bash
export
RUBYLIB=/usr/local/lib/ruby/ruby/1.8/:/usr/local/lib/ruby/ruby/1.8/i386-linux/
/usr/bin/ruby $*

Esto lo hizo. Segun explica porque en su server le cambiaron el PATH a
las
librerías de ruby.
El tenía: /usr/local/lib/ruby/1.8
Y de repente pusieron: /usr/local/lib/ruby/ruby/1.8

Como veis han añadido un directorio más de profundidad.

Despues en "dispach.fcgi" [Que esto es una forma de hacer funcionar
Rails en
produccion no? igual que ningx+mongrelitos o mod_rails+apache no?
Pone esto en "dispach.fcgi":

#!/usr/bin/env [PATH TO YOUR RAILS APP]/public/myruby

Lo hace para decir a rails "He cuidado! ve a buscar lo que quieras
aquí(/usr/local/lib/ruby/ruby/1.8), porque lo han movido de sitio"

Vale, todo lo de arriba es lo que he entendido del link[1], ¿lo he
entendido
bien?

Suponiendo que lo he entendido bien, como puedo hacer yo para cambiar el
RUBYLIB y hacer lo que explicado arriba???
>>Ahora para hacerlo un poco más centralizado y si es posible al estilo
rails, es decir. Yo estoy siguiendo un tutorial en el que voy haciendo
minicodigo como "man.rb"
>>Si me quiero crear modulos que luego pueda usar para estos archivos y que
todos estos modulos esten en un unico directorio "lib". Como lo hago???

Ya está, por hoy me planto. Espero no haber resultado muy pesado

Un saludo

[1]
http://blog.nanorails.com/articles/2006/5/19/arghh...

El 14 de enero de 2009 22:11, Andrés gutiérrez
<andresgutgon@gmail.com>escribió:
7223c62b7310e164eb79c740188abbda?d=identicon&s=25 Xavier Noria (fxn)
on 2009-01-14 23:11
(Received via mailing list)
2009/1/14 Andrés gutiérrez <andresgutgon@gmail.com>:

> Pregunta:
> Cuando hago un include, el modulo que estoy llamando lo busca en el archivo
> del mismo nombre en minusculas en el load_path que tiene definido rails?
> Como dice en la document. cuando yo llamo al modulo con include, ruby llama
> al metodo append_features y este metodo carga todos los: ( the constants,
> methods, and module variables of
>
> this module ) Y en este momento es cuando rails llama a
> const_missing????para saber si el modulo esta en el load_path?

La ejecucion de

    module Foo
      ...
    end

crea una constante corriente y moliente Foo que almacena un objeto de
tipo Module. Es muy parecido a lo que sucede en

    Bar = 0

que define una constante Bar y le asigna un 0.

Cuando escribes

    include Foo

Foo no es ningun token especial del lenguaje, es una constante pura y
dura. Cuando una constante se trata de leer y no ha sido definida
previamente Ruby lanza un error. Esto no tiene relacion con el
include, pasaria igual si pones un

    Zoo

ahi silvestre:

    $ irb
    irb(main):001:0> Zoo
    NameError: uninitialized constant Zoo
        from (irb):1

La variable importante aqui es el ser una constante no definida.

Bien, tu puedes decirle a Ruby que cuando eso suceda ejecute cierto
codigo tuyo en lugar de petar miserablemente. Eso es const_missing.

const_missing puede hacer lo que le plazca. Puede no hacer nada, puede
hacer algo y relanzar el error... no se le asume nada.

En particular, puedes escribir un const_missing para implementar
autoload de cosas, y eso es lo que hace Rails. Por convenio, si se
invoco a const_missing porque la constante User no se conoce, el se
patea su load_path en busca de user.rb. Si encuentra uno lo carga (y
espera que como efecto secundario, al volver de la carga la constante
User haya resultado definida). La implementacion de esto es un poco
mas complicada porque soporta namespaces, pero esa es la idea.
Adce10d7f1dbabcdab8f525a59cec32f?d=identicon&s=25 Andrés Gutiérrez (andresgutgon)
on 2009-01-14 23:36
(Received via mailing list)
Vale, Xavier, te he pillado. Y dices que implementar esto o algo
parecido es
dificil. No me podrías poner en el buen camino. Que quede claro que lo
que
es el concepto me queda claro
pero me sigue uedando la sensación de que si yo me quiero montar una App
churrera en ruby sin rails, No sabría como montarmelo para organizar las
cosas y que pueda acceder a esas constantes (modulos) para usarlos en
mis
clases. Esta App la usaría para ejecutar codigo por consola, para
aprender,
pero a la vez me gustaría tener este codigo centralizado y con librerias
que
pueda usar en otras clases

Un saludo

El 14 de enero de 2009 23:11, Xavier Noria <fxn@hashref.com> escribió:
7223c62b7310e164eb79c740188abbda?d=identicon&s=25 Xavier Noria (fxn)
on 2009-01-14 23:56
(Received via mailing list)
2009/1/14 Andrés gutiérrez <andresgutgon@gmail.com>:

> Vale, Xavier, te he pillado. Y dices que implementar esto o algo parecido es
> dificil. No me podrías poner en el buen camino. Que quede claro que lo que
> es el concepto me queda claro
> pero me sigue uedando la sensación de que si yo me quiero montar una App
> churrera en ruby sin rails, No sabría como montarmelo para organizar las
> cosas y que pueda acceder a esas constantes (modulos) para usarlos en mis
> clases. Esta App la usaría para ejecutar codigo por consola, para aprender,
> pero a la vez me gustaría tener este codigo centralizado y con librerias que
> pueda usar en otras clases

Me parecia entender el objetivo hasta que he llegado a "codigo
centralizado y con librerias que
pueda usar en otras clases". Rails no ofrece eso. Las librerias de
sistema no tienen autoload, solo los ficheros de la aplicacion misma.
Si quieres usar una libreria de sistema has de hacer un require a
mano.
Adce10d7f1dbabcdab8f525a59cec32f?d=identicon&s=25 Andrés Gutiérrez (andresgutgon)
on 2009-01-15 10:37
(Received via mailing list)
Buenos dias Xavier, primero de todo perdoname si no te parezco del todo
coherente. Pero has de entender que en un aprendizaje autodidacta muchas
veces se dan palos de ciego (al menos yo). cuando las cosas no estan
claras.
pero creo que algo he sacado en claro de este hilo:
-Rails si hace el magico autoload con const_missing.
-Las lib de ruby a pelo no se cargan magicamente, sino haciendo un
requiere
"rubygems", require "mysql"

Eso es asi?
Pero mi duda es, haciendolo con requiere. ¿Como sabe mi archivo man.rb
donde
esta "mysql" cuando hago un require?
¿Es algo de los paths?
¿Que quieres decir con "requiere a mano"? Puede sonar como que no me
entero
de nada, pero confia en mi cuando te digo que voy dando micro-pasitos
hacia
delante :-)

Un saludo y gracias de nuevo

El 14 de enero de 2009 23:55, Xavier Noria <fxn@hashref.com> escribió:
39086eb3d9a1437276d07c08ea0c3821?d=identicon&s=25 Guillermo Álvarez Fernández (Guest)
on 2009-01-15 11:05
(Received via mailing list)
_______________________________________________
Ror-es mailing list
Ror-es@lists.simplelogica.net
http://lists.simplelogica.net/mailman/listinfo/ror-es
7223c62b7310e164eb79c740188abbda?d=identicon&s=25 Xavier Noria (fxn)
on 2009-01-15 11:08
(Received via mailing list)
2009/1/15 Andrés gutiérrez <andresgutgon@gmail.com>:

> Buenos dias Xavier, primero de todo perdoname si no te parezco del todo
> coherente. Pero has de entender que en un aprendizaje autodidacta muchas
> veces se dan palos de ciego (al menos yo). cuando las cosas no estan claras.

Nada, nada.

> pero creo que algo he sacado en claro de este hilo:
> -Rails si hace el magico autoload con const_missing.
> -Las lib de ruby a pelo no se cargan magicamente, sino haciendo un requiere
> "rubygems", require "mysql"

Asi es.

> Pero mi duda es, haciendolo con requiere. ¿Como sabe mi archivo man.rb donde
> esta "mysql" cuando hago un require?
> ¿Es algo de los paths?
> ¿Que quieres decir con "requiere a mano"? Puede sonar como que no me entero
> de nada, pero confia en mi cuando te digo que voy dando micro-pasitos hacia
> delante :-)

Con require a mano quiero decir que tu escribes en un fichero

    require "algo"

en lugar de dejar que automagicamente se carge el fichero. No es
"man.rb" quien sabe donde esta, es Ruby que busca "algo.rb" en $: y
las otras opciones que explique en el primer mail.
7223c62b7310e164eb79c740188abbda?d=identicon&s=25 Xavier Noria (fxn)
on 2009-01-15 11:12
(Received via mailing list)
On Thu, Jan 15, 2009 at 11:04 AM, Guillermo Álvarez Fernández
<guillermo@cientifico.net> wrote:

> Yo en plugins suelo tirar bastante de autoload. Es muy sencillo de usar y es
> del core.
> Es tan simple como:
> ModName.autoload(:Feature,'new_feature')

Yep, autoload es de Ruby es una posibilidad que ofrece el lenguaje
para que "configures" la autocarga.

De hecho estuve jugando con la idea de reescribir dependencies.rb (que
es un poco liado) con una aproximacion basada en autoload. Pero una
vez te pones salen cosas que parecen stoppers:

http://groups.google.com/group/rubyonrails-core/br...
Adce10d7f1dbabcdab8f525a59cec32f?d=identicon&s=25 Andrés Gutiérrez (andresgutgon)
on 2009-01-15 11:15
(Received via mailing list)
>>Con require a mano quiero decir que tu escribes en un fichero

   >>require "algo"

>>en lugar de dejar que automagicamente se carge el fichero. No es
>>"man.rb" quien sabe donde esta, es Ruby que busca "algo.rb" en $: y
>>las otras opciones que explique en el primer mail.

Vale, me queda claro, me tengo que mirar lo de $: y RUBYLIB. Si yo
quiero
que mis modulos los carge cualquier fichero que tenga
en mi SO, tengo que meterlos en este PATH o añadir un directorio mio
(lib) a
ese PATH?
Esto es asi? se puede hacer lo que digo arriba?

Lo de autoload, me lo miro con más calma y os cuento

Gracias a los dos


El 15 de enero de 2009 11:07, Xavier Noria <fxn@hashref.com> escribió:
7223c62b7310e164eb79c740188abbda?d=identicon&s=25 Xavier Noria (fxn)
on 2009-01-15 11:25
(Received via mailing list)
2009/1/15 Andrés gutiérrez <andresgutgon@gmail.com>:

> que mis modulos los carge cualquier fichero que tenga
> en mi SO, tengo que meterlos en este PATH o añadir un directorio mio (lib) a
> ese PATH?
> Esto es asi? se puede hacer lo que digo arriba?

Eso es. De hecho normalmente solo se instalan librerias empaquetadas a
nivel de sistema.

Si tu intencion es que unas tuyas sean visibles en todo el sistema te
recomiendo que o bien sigas por el camino de RUBYLIB, o bien hagas una
gema de ellas (mirate como hacer un .gemspec + gem build) e instalar
esa gema.

Ese segundo camino necesita de mas background de todos modos,
empezaria por entender bien $: y RUBYLIB y el primer mail solo-Ruby.
Adce10d7f1dbabcdab8f525a59cec32f?d=identicon&s=25 Andrés Gutiérrez (andresgutgon)
on 2009-01-15 11:34
(Received via mailing list)
Ese segundo camino necesita de mas background de todos modos,
empezaria por entender bien $: y RUBYLIB y el primer mail solo-Ruby

Por ahi tiro, gracias

El 15 de enero de 2009 11:25, Xavier Noria <fxn@hashref.com> escribió:
This topic is locked and can not be replied to.