Construindo Querys com ActiveRecord e Arel

Recentemente estava assistindo essa talk da RailsConf 2014 e achei interessante a forma apresentado por Cameron Dutro de como construir querys com ActiveRecord e Arel.

Ele mostra alguns exemplos de pesquisa utilizando strings em condições e joins e o porque isso pode ser ruim..

Vejamos essa query:

User.where("email ILIKE ?", '%teste%')

Por utilizarmos string para especificar as condições de busca, podemos acabar usando uma sintaxe exclusiva de um banco de dados..

No exemplo acima, faço uso de ILIKE, que existe no PostgreSQL, mas não no MySQL. Essa é apenas uma das dores de cabeça que podemos ter ao usar strings pra esse tipo de coisa.

Como alternativa, Dutro supõe o uso do Arel para a construção de querys mais limpas e fáceis de manter. Veja como ficaria a busca acima com Arel:

User.where(User.arel_table[:email].matches("%teste%"))

O trecho acima, gera o mesmo SQL esperado que o primeiro:

SELECT "users".* FROM "users"  WHERE ("users"."email" ILIKE '%teste%')

Brincando com Arel

Veja abaixo mais alguns exemplos de como podemos brincar com Arel em nossas querys seguido do correspondente SQL..

Eq

User.where(User.arel_table[:email].eq('teste@provedor.com'))
SELECT "users".* FROM "users"  WHERE "users"."email" = 'teste@provedor.com'

Not Eq

User.where(User.arel_table[:email].not_eq('teste@provedor.com'))
SELECT "users".* FROM "users"  WHERE ("users"."email" != 'teste@provedor.com')

In

User.where(User.arel_table[:email].in(['teste@provedor.com', 'outro@provedor.com']))
SELECT "users".* FROM "users"  WHERE "users"."email" IN ('teste@provedor.com', 'outro@provedor.com')

Temos ainda outros operadores de comparação que podem ser vistos aqui.

Or e And

Achei legal também que podemos usar os operadores or e and.. Veja:

User.where(
  User.arel_table[:email].eq(
    'teste@provedor.com'
  ).or(
    User.arel_table[:gender].eq('m').and(
      User.arel_table[:name].eq('Teste')
    )
  )
)
SELECT "users".* FROM "users"  WHERE (
  (
    "users"."email"  = 'teste@provedor.com' OR 
    "users"."gender" = 'm' AND "users"."name" = 'Teste'
  )
)

Arel Helpers Gem

Uma coisa chata é ter que ficar colocando .arel_table toda vez depois do nome do model para acessar os atributos..

Não só para resolver esse problema, mas também outros e adicionar algumas features legais (como possibilitar a criação de query builders), o próprio Cameron Dutro criou uma gema chamada arel-helpers.

Fica a seu critério utilizá-la ou não.

Essa foi a dica de hoje. O que acharam?

Abraços.

Written on July 28, 2014

Share: