Mal comecei a aprender Ruby e, já nos primeiros testes, estou precisando acessar banco de dados. Imaginava que, como existem as classes Array, String, Hash, Integer, etc., também haveria uma DB e seria só aprendê-la a usar. Mas, como em outras linguagens, acessar BD não é uma coisa única (isto é, um jeito único já provido como recurso nativo da linguagem).
Nesta página aprendi que há 3 formas populares de usar BD em Ruby:
1. Pelo driver do banco de dados. Isso varia muito com o driver. Exemplo:
results = mysql.query("SELECT * from rocks;") # mysql
results = conn.exec('select * from rocks') # postgree
results.each do |row|
...
end
Isso inviabiza mudanças de base de dados no futuro, pois exige alterar todo o código.
2. Pela interface DBI, que é uma interface única para diferentes bancos de dados:
query = dbh.prepare("SELECT * FROM rocks") # o mesmo código para diferentes bancos
query.execute()
while row = query.fetch() do
...
end
Para quem vem do PHP, como eu, a primeira interface lembra o
MySQLi, pela semelhança, e a segunda lembra o
PDO, pela filosofia de prover uma interface independente do BD.
Na época da decisão entre o MySQLi e o PDO, optei pelo primeiro, porque não pretendia mudar de BD e porque soube que o PDO não teria como aproveitar todos os recursos do MySQL, justamente por seu desapego a algum BD em particular.
No entanto, o MySQLi, mesmo tendo uma interface orientada a objetos, não me satisfazia, pois parecia uma linguagem procedural disfarçada de OO. Então criei algumas classes para realizar
queries e trabalhar com resultados à maneira OO, com
method chaining, heranças e tudo o que a orientação a objetos oferece de útil e produtivo.
No exemplo acima, seria assim:
$results = $my->new_query()->from_tabela('rocks')->lc() # retorna uma matriz linhas x colunas
foreach($results as $row) {
...
}
Mas é muito mais que isso. Sempre achei que os registros deveriam ser objetos, com métodos como
insert,
update, etc. O jeito mais apropriado de usá-las seria, por exemplo:
$query = $my->new_query()->from_tabela('rocks')->add_cond('name like ?', 'a%');
while ($row = $query->fetch()) {
$id = $row->valor('id');
$name = $row->valor('name');
...
}
# alterando um campo
$row->set('name', 'Turquesa')->update();
# inserindo um campo
my_registro::_new($my, 'rocks')->set('name', 'Ametista')->insert();
Implementei todas essas coisas.
Bom, eu havia mencionado que aprendi 3 formas de usar BD em Ruby, mas só falei de duas.
3. A terceira é o
ActiveRecord, muito usada pelo framework
Ruby on Rails.
Quando vi os códigos de exemplo me apaixonei. Me identifiquei imediatamente. É a versão pronta para Ruby do que eu havia construído manualmente para PHP.
Nele, as tabelas são classes e as linhas são suas instâncias. É assim que as coisas têm que ser!
queryresults = Rock.find(:all)
queryresults.each do |row|
print row.id, " ", row.name, "\n"
end
# inserindo nova rocha:
newrow = Rock.new
newrow.name = "Basalto"
newrow.save
Ok, vamos aprender ActiveRecord!
Pesquisando no Google, abri algumas páginas e uma delas era sobre um tal de
Sequel, que se dizia um toolkit para BD em Ruby. "Um concorrente do ActiveRecord", pensei. Ora, se o AR é tão usado no Rails, por que perder tempo aprendendo outra coisa? Mas o curioso aqui foi fuçar e descobriu
uma comparação em que o Sequel se mostra muito superior! (veja sobre as diferenças).
Vejamos aquele mesmo exemplo:
# select * from rocks
DB[:rocks].each do |row|
...
end
# com uma condição
DB[:rocks].filter{:id => [10, 15, 17]}.each do |row|
...
end
# inserindo uma rocha
DB[:rocks].insert(:name => 'Quartzo')
Conclusão: mal comecei a aprender o ActiveRecord, que me parecia o melhor dos melhores, e encontro algo melhor ainda! (De fato, eu gostei tanto que nem terminei de ler aquela comparação: eu precisava redigir este post!)
Muito legal a comunidade do Ruby oferecer recursos como esses! É um grande atrativo para novos usuários.