Executando SQL no Rails
Leia em 1 minuto
Às vezes precisamos realizar consultas que não pertencem a nenhum modelo no Rails. Uma maneira de fazer isso é utilizando o método execute
. Veja um exemplo:
# setting a variable
# with the current connection
conn = ActiveRecord::Base.connection
result = conn.execute "SELECT id, email FROM users LIMIT 3"
# => #<Mysql::Result>
Como resultado, você recebe um objeto Mysql::Result
, que pode ser iterado da seguinte maneira:
result = conn.execute "SELECT id, email FROM users LIMIT 2"
result.each do |user|
puts "id: %s" % user[0]
puts "email: %s" % user[1]
puts
end
Normalmente, precisamos fazer consultas baseadas em valores passados pelo usuário. É extremamente importante que você tome os cuidados necessários para não sofrer um ataque através de SQL Injection. Para que isto não aconteça, você deve utilizar o método quote
:
query = "SELECT id, email FROM users WHERE email = %s" % conn.quote("' OR 1=1 #")
puts query
# => SELECT id, email FROM users WHERE email = '\' OR 1=1 #'
Além do método execute
, você pode utilizar outros mais específicos como é o caso do método select_all
. Este método retorna um array de hashes, com o nome das colunas como índice, tornando mais simples a iteração.
result = conn.select_all "SELECT id, email FROM users LIMIT 2"
result.each do |user|
puts "id: %s" % user['id']
puts "email: %s" % user['email']
puts
end
Para os casos em que tudo o que você precisa é de apenas uma linha como resultado, você pode utilizar o método select_one
:
result = conn.select_one("SELECT COUNT(*) AS total FROM users")
puts result['total']
No Rails, todos os modelos estendem a classe ActiveRecord::Base
. Por isso, os métodos acima também estão disponíveis no modelo.
class User < ActiveRecord::Base
def self.all
connection.select_all "SELECT id, email FROM users"
end
end
puts User.all
# => [{"id"=>"1", "email"=>"user@example.com"}, {"id"=>"2", "email"=>"another@example.com"}]
Lembre-se que não é nenhuma vergonha utilizar SQL diretamente no Rails. O que o ActiveRecord faz é nos poupar das tarefas rotineiras. Já para as mais complexas, você provavelmente vai precisar de uma das soluções acima. Para mais informações, acesse a documentação do ActiveRecord.