Nel post precedente ho tralasciato parecchie cose su come gestire file e directory con Ruby. Ne è nata una discussione, credo sia il caso di approfondire l’argomento. Anche perché non ci sono cose nuove, non ancora affrontate nel corso.
Una cosa che ho dato per scontata e forse non lo è: in Ruby ci sono sempre diverse vie per fare una cosa, non so se è un bene o no, ma è la filosofia di Matz. Ancora: ci sono istruzioni che nel tempo cambiano; quello che era OK con la revisione x.y
non vale più dalla z.0
in poi. Non proprio l’ideale, ma dobbiamo conviverci.
require
e load
Le due istruzioni sembrano uguali, consentono entrambe di usare nello script corrente le risorse (oggetti, in Ruby tutto è un oggetto) definite al loro interno come se fossero nel file corrente. C’è però una grossa differenza: require
va usato una sola volta gli oggetti vengono memorizzati mentre load
è solo un modo per evitare il copia-incolla da un file a quello corrente, evitando di doverlo rifare quando si modifica l’originale; quindi può essere usato più volte nello stesso script (se uno è pasticcione, altrimenti non credo sia necessario).
Ecco un esempio minimo che usa sia require
che load
(loreq.rb):
#!/usr/bin/ruby # encoding: UTF-8 # loreq.rb load 'lo-0.rb' puts "sono nel main: #{__FILE__}" require './req.rb' puts "v = #{$v}" load 'lo-1.rb' puts "v2 = #{$v2}"
ci servono 3 file, 2 per load
e 1 per require
, eccoli:
#!/usr/bin/ruby # encoding: UTF-8 # lo-0.rb puts "sono nel file: #{__FILE__}"
#!/usr/bin/ruby # encoding: UTF-8 # rec.rb $v = 8
#!/usr/bin/ruby # encoding: UTF-8 # lo-1.rb $v2 = 42
Inoltre nella variabile di sistema __FILE__
viene memorizzato il nome del file corrente. Altre cose sulle directories verranno raccontate in seguito, per adesso vediamo cosa succede se lo eseguiamo:
Tutto come previsto, anche le variabili definite nei file secondari sono visibili in quello principale. Sappiamo già che quelle il cui nome inizia con $
sono globali, vero?
Ma se questo è logico per require
con load
la variabile dev’essere globale? Uh… ehmm, io penso che …, dai proviamo (testload.rb e incload.rb):
#!/usr/bin/ruby # encoding: UTF-8 # testload.rb load 'incload.rb' puts "nel main: prova = #{prova}"
# incload.rb prova = 42 puts "nel file incluso: prova = #{prova}"
OPS! no! load
non si comporta come dovrebbe; la variabile dichiarata al suo interno non viene vista nel main. Quindi, se non è un bug che verrà corretto, non usare
ma loadrequire
.
Accedere a file e directory
Non sempre i file e le risorse che ci servono sono nella stessa directory (cartella). Nessun problema, Ruby è in grado di gestire benissimo la cosa (quasi), ecco un primo esempio (path.rb):
#!/usr/bin/ruby # encoding: UTF-8 # path.rb nomefile = __FILE__ puts "nomefile = #{nomefile}" pathname = File.expand_path(nomefile) puts "pathname = #{pathname}" dirname = File.expand_path('../', pathname) puts "dirname = #{dirname}" t = dirname + '/' puts "inutile ma dirname + '/' = #{t}" home = File.expand_path('~') puts "home = #{home}"
Tutto come previsto, il modulo File
fa parte di quelli predefiniti, immediatamente disponibili, senza usare require.
L’operatore +
concatena le stringhe, come già visto. Per trattare i pathnames in realtà non serve ma volendo c’è. Ovviamente ~
è definita solo per Linux. Per Windows si può usare ENV
, un hash che mappa le variabili di ambiente (environment), così (hvs.rb):
#!/usr/bin/ruby # encoding: UTF-8 # hvs.rb home = ENV['HOME'] puts "home = #{home}"
Attenzione: è un hash, le parentesi sono quadre 😉
FileUtils
Ci sono ancora tante cose da vedere; per esempio c’è tutto il modulo FileUtils
. Che (almeno da me) non è che funzioni proprio come dovrebbe. Eccone un assaggio, maggiori informazioni, forse, in futuro (fu-pwd.rb):
#!/usr/bin/ruby # encoding: UTF-8 # fu-pwd.rb require 'fileutils.rb' fdir = FileUtils.pwd puts "directory corrente = #{fdir}" questo = File.join(fdir, __FILE__) puts "questo = #{questo}" f = File.file?(questo) d = File.directory?(questo) print f, " ", d, "\n"
Notare che il modulo dev’essere inserito con require
(riga 6) e che il nome del file è tutto minuscolo. Le funzioni contenute sono elencate qui.
Non tutte funzionano, anche perché il modulo si riferisce a una versione diversa da quella che sto utilizzando. resta indispensabile il modulo File
.
Notare alla riga 11 il modo sicuro per concatenare i path e i predicati file?
e directory?
(righe 14 e 15). Ne esistono parecchi altri, tra i quali exists?
Per oggi basta 😀 e per un po’ basta Ruby, ci sono altre cose in coda 😉