Concludiamo il capitolo relativo ai DB con un'altra soluzione leggera ma dalla sintassi alquanto rubyish: KirbyBase.
KirbyBase è un DBMS molto leggero e interamente scritto in Ruby. I dati vengono salvati su file di testo e possono essere eventualmente modificati a mano, è possibile usarlo sia in modalità embedded sia in modalità client/server. Può essere visto come una via di mezzo tra i file di testo semplice e i database di tipo SQL.
Con l'aiuto di irb
vediamone alcuni esempi. Iniziamo con la creazione di una database e di una tabella.
Creare un DB e una tabella
$ irb --simple-prompt >> require 'rubygems' >> require 'kirbybase' >> db = KirbyBase.new >> book = db.create_table(:libro, :titolo, :String, :autore, :String, :anno, :Integer)
Il metodo create_table
prende come argomenti il nome della tabella e il nome e il tipo di ogni colonna. I tipi disponibili sono: String
, Integer
, Float
, Boolean
, Time
, Date
, DateTime
, Memo
, Blob
, e YAML
. Per ogni campo è possibile specificare anche alcune proprietà come il valore di default, l'obbligatorietà del campo, l'indicizzazione e riferimenti ad altri record in altre tabella.
Dopo queste operazioni avremo nella nostra directory di lavoro un file dal nome libro.tbl
Contenuto di un file Kirby
$ cat libro.tbl 000000|000000|Struct|recno:Integer|titolo:String|autore:String|anno:Integer
dove recno:Integer
è un campo che viene aggiunto automaticamente e rappresenta la chiave primaria.
Per popolare la nostra tabella si usa il metodo insert
>> book.insert("Reduce","Giovanni Lindo Ferretti",2006) => 1 >> book.insert("Il bosco degli urogalli","Mario Rigoni Stern",1962) => 2
In alternativa è possibile usare degli hash, delle strutture o dei blocchi:
>> book.insert do |l| >> l.titolo = "Memorie dal sottosuolo" >> l.autore = "Fedor Dostoevskij" >> l.anno = 1864 >> end => 3
Il valore ritornato rappresenta il numero di record all'interno della tabella. Per aggiornare i valori immessi si utilizza il metodo update, mentre per cancellarli esiste il metodo delete. Ecco come appare adesso il file libro.tbl
$ cat libro.tbl 000003|000000|Struct|recno:Integer|titolo:String|autore:String|anno:Integer 1|Reduce|Giovanni Lindo Ferretti|2006 2|Il bosco degli urogalli|Mario Rigoni Stern|1962 3|Memorie dal sottosuolo|Fedor Dostoevskij|1864
Vediamo infine degli esempi di selezione. Per ricavare tutto il contenuto della tabella basta utilizzare il metodo select
senza specificare null'altro:
>> ris = book.select => [#<struct #<Class:0xb7a98f14> recno=1, titolo="Reduce", autore="Giovanni Lindo Ferretti", anno=2006>, #<struct #<Class:0xb7a98f14> recno=2, titolo="Il bosco degli urogalli", autore="Mario Rigoni Stern", anno=1962>, #<struct #<Class:0xb7a98f14> recno=3, titolo="Memorie dal sottosuolo", autore="Fedor Dostoevskij", anno=1864>]
Il risultato viene restituito in un oggetto di tipo KBResultSet
. Se invece si vogliono visualizzare solo alcune colonne basta indicarle come argomento:
>> ris_titolo = book.select(:titolo) => [#<struct #<Class:0xb79ac8d0> titolo="Reduce">, #<struct #<Class:0xb79ac8d0> titolo="Il bosco degli urogalli">, #<struct #<Class:0xb79ac8d0> titolo="Memorie dal sottosuolo">]
Per meglio definire la ricerca è possibile utilizzare i blocchi. Ad esempio per estrarre solo i libri pubblicati dopo il 2000 si può scrivere:
> ris_duemila = book.select(:titolo) {|l| l.anno > 2000} => [#<struct #<Class:0xb79a6638> titolo="Reduce">]
Di notevole interesse è il metodo to_report che stampa in maniera leggibile il risultato della selezione:
>> book.select.to_report => "recno | titolo | autore |anno ---------------------------------------------------------------- 1 | Reduce | Giovanni Lindo Ferretti | 2006 2 | Il bosco degli urogalli | Mario Rigoni Stern | 1962 3 | Memorie dal sottosuolo | Fedor Dostoevskij | 1864 "
Da questi brevi esempi si nota subito che si gestisce il database non con delle query SQL ma attraverso semplice codice Ruby. Alcuni dettagli per finire: per utilizzare KirbyBase in modalità client/server basta sostituire la riga
>> db = KirbyBase.new
con una del genere
>> db = KirbyBase.new(:client, 'localhost', 7777)
dove viene specificato l'host e la porta del server.
È possibile offuscare il contenuto della tabella impostando l'attributo encrypt
a true
al momento della creazione della tabella:
book = db.create_table(:libro, :titolo, :String, :autore, :String, :anno, :Integer) do |r| r.encrypt = true end
Per un elenco completo dei metodi disponibile e per gli aspetti avanzati rimando alla documentazione ufficiale reperibile sul sito del progetto.