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
TLS 1.3 has been out for a little over a year now, but it has been unavailable in Phoenix due to erlang’s handling of ssl. With the most ...
New
Here is an example of a Mix application that utilizes Cowboy to handle websocket connections. If anyone has an idea about making this wor...
New
I’m posting this for developers who are totally new to Phoenix like myself. This is all probably obvious to more skilled Phoenix develope...
New
I was preparing to deploy a production application to AWS Fargate, and to practice I wanted to play with DNS polling and node discovery o...
New
pipe into case? I use that fairly frequently…unless I’m misunderstanding what you’re wanting…could be.. its still very early…
str = "Hel...
New
Another cool plugin for Neovim, GitHub - jmbuhr/otter.nvim: Just ask an otter! 🦦 · GitHub makes it possible to run linters for embedded c...
New
Ok, so I am so excited to share with you the most interesting setup I have made for Elixir/Phoenix today. Why? Because if you trust me, i...
New
I’ll post this here, It might help someone in the future.
Feedback is greatly appreciated.
I use it with direnv on NixOS, It should wor...
New
In the process of developing a Phx-based multiplayer experience, I found myself with so many browser tabs open with Elixir gaming resourc...
New
I couldn’t find any guides that worked well with Phoenix 1.6.0 and esbuild. I hope this helps people test the waters and eases you into t...
New
Other popular topics
Anybody knows a comprehensive comparison of Django and Phoenix, thanks for the help.
Where are they similar?
Where do they differ the m...
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
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
Hey,
Just curious what are the main benefits of Elixir compared to Clojure?
When is Elixir more useful than Clojure and vice versa?
Th...
New
i’m a new one to elixir
which editor can i use
vs code? or atom?
Thanks! :smiley:
New
Hi folks,
Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
New
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar.
I p...
New
I am going through the kafka architecture. All the features what the kafka is providing are already in Erlang. I would like hear your opi...
New
I had some trouble figuring out how to make many-to-many associations work. Once I got it working, I wrote a blog post. Because I’m a nov...
New
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #javascript
- #code-sync
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








