I love the autoload functionality of Ruby; tuttavia, è going away in future versions of Ruby poiché non è mai stato thread-safe.Autoloading di classi in Ruby senza il suo `autoload`
Quindi ora vorrei far finta che sia già andato e scrivere il mio codice senza di esso, tramite implementando il meccanismo di caricamento lento io stesso. Mi piacerebbe implementarlo nel modo più semplice possibile (non mi interessa la sicurezza del thread in questo momento). Ruby dovrebbe permetterci di farlo. inizio
Let aumentando una classe const_missing
:
class Dummy
def self.const_missing(const)
puts "const_missing(#{const.inspect})"
super(const)
end
end
Rubino chiamerà questo metodo speciale quando si tenta di fare riferimento a una costante in 'Dummy' che manca, ad esempio, se cerchiamo di fare riferimento a "Dummy: : Ciao ", chiamerà const_missing
con il simbolo :Hello
. Questo è esattamente quello che ci serve, quindi cerchiamo di prendere ulteriormente:
class Dummy
def self.const_missing(const)
if :OAuth == const
require 'dummy/oauth'
const_get(const) # warning: possible endless loop!
else
super(const)
end
end
end
Ora, se facciamo riferimento "Dummy :: OAuth", sarà necessario il file "fittizio/oauth.rb" che dovrebbe definire la " Dummy :: OAuth "costante. C'è una possibilità di un ciclo infinito quando chiamiamo const_get
(dal momento che può chiamare internamente) const_missing
, ma guardarsi da questo è al di fuori dello scopo di questa domanda.
Il grosso problema è che l'intera soluzione si interrompe se esiste un modulo denominato "OAuth" nello spazio dei nomi di livello superiore. Il riferimento a "Dummy :: OAuth" salterà il suo const_missing
e restituirà "OAuth" dal livello superiore. La maggior parte delle implementazioni di Ruby farà anche un avvertimento su questo:
warning: toplevel constant OAuth referenced by Dummy::OAuth
This was reported as a problem way back in 2003 ma non riuscivo a trovare la prova che il core team di Ruby era mai preoccupato per questo. Oggi, le implementazioni di Ruby più popolari hanno lo stesso comportamento.
Il problema è che const_missing
viene saltato automaticamente a favore di una costante nello spazio dei nomi di livello superiore. Ciò non accadrebbe se "Dummy :: OAuth" fosse dichiarato con la funzionalità autoload
di Ruby. Qualche idea su come aggirare questo?
Questo mi sembra un suggerimento stupido, ma si può guardare il sorgente C di 'autoload'? Sono sicuro che puoi trovarlo da qualche parte nella sorgente Ruby. Se non puoi farlo direttamente in Ruby, c'è la possibilità di creare un'estensione C (che ha accesso al lato inferiore dell'interprete). – Linuxios
È un'opzione. – mislav
suona come una cosa a forza bruta, ma non potresti 'remove_const' nella classe di primo livello? – phoet