fuelen
Cond in Ecto query DSL
Hi all!
Just want to share a small code snippet which allows writing CASE expressions using macro which is similar to cond.
Here is an example of usage:
import Ecto.Extension.Query.API
import Ecto.Query
from users in "users",
select: %{
email: users.email,
role_label:
cond_ do
users.role == "director" -> "DIRECTOR!"
users.inserted_at < ago(6, "month") -> "OLD!"
true -> type(users.role, :string)
end
}
generated SQL:
SELECT u0."email", CASE WHEN u0."role" = 'director' THEN 'DIRECTOR!' WHEN u0."inserted_at" < $1::timestamp + (-6::decimal::numeric * interval '1 month') THEN 'OLD!' WHEN TRUE THEN u0."role"::varchar END FROM "users" AS u0
and implementation:
defmodule Ecto.Extension.Query.API do
defmacro cond_(do: block) do
bindings =
block
|> Enum.reduce([], fn
{:->, _, [[clause], branch]}, acc ->
[branch, clause | acc]
end)
|> Enum.reverse()
bindings_number = length(bindings)
sql =
IO.iodata_to_binary([
"CASE",
List.duplicate(" WHEN ? THEN ?", div(bindings_number, 2)),
" END"
])
quote do
fragment(unquote(sql), unquote_splicing(bindings))
end
end
end
I hope someone will find this useful 
Most Liked
fuelen
Well, this is my first attempt to implement @hauleth idea. Some kind of composability is still possible
defmodule CustomEctoFrom do
defmacro __using__(map) do
quote do
require Ecto.Query
defmacro from(expr, kw) do
kw = CustomEctoFrom.traverse(kw, unquote(map))
quote do
Ecto.Query.from(unquote(expr), unquote(kw))
end
end
end
end
def traverse({function, args}, map) when is_atom(function) do
{function, traverse(args, map)}
end
def traverse({function, meta, args}, map) do
function =
case Map.fetch(map, function) do
{:ok, aliased_to} -> aliased_to
:error -> function
end
{traverse(function, map), meta, traverse(args, map)}
end
def traverse(kw, map) when is_list(kw) do
for elem <- kw, do: traverse(elem, map)
end
def traverse(term, _map), do: term
end
defmodule OtherModuleWithExtensions do
defmacro concat(a, b) do
quote do
fragment("? || ?", unquote(a), unquote(b))
end
end
end
defmodule Test do
import Ecto.Extension.Query.API
import OtherModuleWithExtensions
use CustomEctoFrom, %{cond: :cond_, <>: :concat}
def test do
from users in "users",
select: %{
full_name: users.first_name <> " " <> users.last_name,
email: users.email,
role_label:
cond do
users.role == "director" -> "DIRECTOR!"
users.inserted_at < ago(6, "month") -> "OLD!"
true -> type(users.role, :string)
end,
id: users.id
}
end
end
1
Popular in Guides/Tuts
I have published an elixir project with using Travis CI.
I would like to share some tips & thoughts that I was getting through this ...
New
Hi everyone!
I’m the founder of Render, a new cloud provider with native support for Elixir. When we launched Elixir support the most po...
New
I just published an article on creating Phoenix LiveView modals using Tailwind CSS and AlpineJS.
New
Greetings: I just wrote a step-by-step guide on building a Phoenix 1.3 JWT Auth API with Guardian JWTs and Comeonin password hashing.
I ...
New
Here is a quick guide to uploading a file from the browser to DO spaces.
It is crude, but will hopefully save sometime time and frustrat...
New
Hi! I recently finished adding authentication to my Phoenix API, so I wanted to share what I learned.
I haven't created authentication ...
New
So my main OS is Windows, I do must of my work with it, Elixir and vscode elixirls works just fine when you’re working only with elixir, ...
New
I’m excited about the new LiveComponents feature in LiveView, but I haven’t seen much written on it, so I decided to write a couple of ar...
New
POST IN CONSTRUCTION
Process for compile erlang otp 20 with odbc-unix for Oracle connections on Solaris 11.3 for 64 bits:
Introductio...
New
I write an article Parameterized testing with ExUnit.The key concept is using ExUnit.Case.register_test/4 such as
ExUnit.start()
defmod...
New
Other popular topics
Hi everyone,
One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New
What is the proper way to load a module from a file in to IEX?
In the python world, doing something like this pretty standard:
from ....
New
I am trying to figure out how Mix knows whether the environment is test, dev, or prod -- where is this set?
Thanks.
New
Good day to you all.
I have been struggling to get a query involving like and ilike to work.
Can anyone assist me on this, please?
pro...
New
How to set Jason to encode all fields in ecto schema, I don’t care about security and implementing only is taking long list of attributes...
New
Hello,
I am trying to convert my lists to string without losing brackets.For start i have 3 map. They look like these
buyer = %{
id: ...
New
If I have a string “1000 cfu/ml” . I want to remove the characters and / and space . So the string is like this
"1000"
What is the ...
New
Could someone help me? I'm making my first elixir program, number guessing game. I can't figure out how to convert the user's guess from ...
New
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: )
Hello all, this is ...
New
We’ve put together this wiki for Phoenix LiveView - please feel free to add any info you feel is worth including.
What is Phoenix LiveV...
New







