Quem trabalhou com OOP em PHP e começa a aprender Ruby vai logo sentir falta do
__autoload do PHP.
O Ruby já tem
autoload, mas na prática parece inútil, para quem vem do PHP.
No Ruby, o objetivo do autoload é apenas não ocupar memória sem necessidade, deixando para carregar os arquivos somente quando a classe ou módulo forem requeridos. Muito bem, mas para isso você precisa digitar mais do que digitaria com
require: além de especificar o nome do arquivo, tem que digitar as constantes (classes, etc.) que estão no arquivo. Por exemplo:
autoload :MinhaClasse, "minhaclasse.rb"
Eu penso que os computadores foram feitos para ajudar o homem, e isso inclui o programador. Do ponto de vista do programador (e não da máquina), seria muito mais fácil usar:
require "minhaclasse.rb"
A não ser que os recursos sejam críticos, o tempo de desenvolvimento e manutenção é mais importante neste caso.
No PHP, você define apenas uma vez uma função que irá adivinhar o nome do arquivo a partir do nome da classe, e aí nunca mais precisa se preocupar! Você não tem que especificar nada!!! Quando for feita uma referência a "MinhaClasse", a função
__autoload irá converter isso para um nome de arquivo (por exemplo, "minhaclasse.inc"; você pode programar
__autoload como quiser) e tentará incluir esse arquivo. É muito mais prático!
Felizmente o Ruby é uma linguagem muito maleável e, baseado em uma
dica, desenvolvi a minha versão:
# autoload como em PHP
# http://gigawiki.com/sony/autoload-do-ruby-como-no-php
#
# altera Object#const_missing
#
class Object
# trata-se de um método da classe, e não do objeto
class << self
# mantém o método original em old_const_missing, e o torna privado
alias_method :old_const_missing, :const_missing
private :old_const_missing
# redefine método chamado quando a constante não é encontrada
def const_missing(const)
# adivinha um nome de arquivo (use seu algoritmo preferido)
filename = const.to_s.downcase
begin
# tenta requeri-lo
require filename
# se conseguiu, retorna a constante que faltava
const_get(const)
rescue LoadError => e
if e.message.include? filename
# se não conseguiu porque essa constante não existe, usa o algoritmo antigo.
old_const_missing(const)
else
# se não conseguiu por outro motivo, manifeste-se.
raise
end
end
end
end
end