O mundo do Elixir é funcional. Não existem objetos ou instâncias. Neste caso, eu me pergunto: eu preciso de ORM?
Minha resposta a esta pergunta é não.
Eu preciso de dados. Dados puros que venham direto do banco de dados. Outra questão que me vem à mente: preciso de um DSL para consultar o banco de dados?
Novamente, não!
Temos uma grande linguagem criada para consultar bancos de dados. O SQL, lembra?
E se eu pudesse criar uma função em Elixir que tenha o corpo de um SQL? E se eu pudesse usar esta função exatamente como qualquer outra função Elixir? Seria ótimo, não seria?
Podemos fazer isso utilizando o poderoso sistema de macro do Elixir. No entanto, esta também é uma boa maneira de aprender como as macros do Elixir funcionam.
Para fazer isso, eu comecei a escrever o Defql . O Defql é um pacote Elixir que fornece uma maneira simples de definir funções com a linguagem SQL. Como ele funciona?
Consultando bancos de dados
Este pacote fornece a macro defquery. Com ela, você pode definir a função que contenha uma consulta SQL. Por exemplo:
defmodule UserQuery do use Defql defquery get_by_blocked(blocked) do "SELECT * FROM users WHERE blocked = $blocked" end end
É muito limpa, fácil de ler, e a melhor parte: suporta parâmetros. Brilhante!
Chamar essa função também é muito simples.
Dependendo do parâmetro fornecido, vamos bloquear ou desbloquear os usuários.
UserQuery.get_user(false) # => {:ok, []} UserQuery.get_user(true) # => {:ok, []}
Agora podemos facilmente consultar nosso banco de dados e obter um resultado.
E quanto ao INSERT, o UPDATE, e o DELETE? Boa pergunta! Você pode criar as consultas com defquery, mas há outra maneira.
CRUD
Este pacote também contém outras macros. Veja este exemplo:
defmodule UserQuery do use Defql defselect get(conds), table: :users definsert add(params), table: :users defupdate update(params, conds), table: :users defdelete delete(conds), table: :users end
O que elas vão fazer? Essas macros irão criar funções CRUD comuns. Então você não precisa escrever cada consulta com o SQL. Consultas simples são criadas para você assim. Como posso chamá-los? Aqui está um exemplo:
UserQuery.get(id: "3") # => {:ok, [%{...}]} UserQuery.add(name: "Smbdy") # => {:ok, [%{...}]} UserQuery.update([name: "Other"],[id: "2"]) # => {:ok, [%{...}]} UserQuery.delete(id: "2") # => {:ok, [%{...}]}
Configuração
A configuração também é fácil. Você pode usar de duas maneiras.
Com uma conexão Ecto existente:
config :defql, connection: [ adapter: Defql.Adapter.Ecto.Postgres, repo: Taped.Repo ]
Com uma conexão independente:
config :defql, connection: [ hostname: "localhost", username: "username", password: "password", database: "my_db", pool: DBConnection.Poolboy, pool_size: 1 ]
O que falta?
Claro, ainda é muito cedo, mas o suporte ao postgres funciona bem. Faltam poucas coisas:
- Suporte ao MySQL
- Suporte IN com array %{id: [1,2,3]}
- Adaptador de limpeza do ECTO
- Erros de suporte aos bancos de dados
Resumo
Usando Defql temos uma forma muito clara, simples e poderosa para interagir com um banco de dados.
Links
- Repositório Github: https://github.com/fazibear/defql
- Hex do pacote: https://hex.pm/packages/defql
- Documentação: https://hexdocs.pm/defql
Espero que tenha sido útil para você. Obrigado pela leitura!
***
Artigo publicado originalmente em https://blog.fazibear.me/sql-queries-as-elixir-functions-5f8b1d67169e#.jt2j0ac7d