Search code examples
elixirecto

Fragments reuse


Is it somehow possible to reuse fragments?

In an example like this

def unpublished_by_title(title) do
  from p in Post,
    where: is_nil(p.published_at) and
           fragment("downcase(?)", p.title) == ^title
end

It seems like it would be very convenient to be able to extract fragment-part into a separate function so that it can be reused in other places, e.g.:

def unpublished_by_title(title) do
  from p in Post,
    where: is_nil(p.published_at) and
           downcase(p.title) == ^title
end

def downcase(title) do
  fragment("downcase(?)", ^title)
end

however, after trying many different variations it seems like this wouldn't work because of macro expansions or something like that. Any ideas?


Solution

  • You are right, queries are composed at compile time. Because of this, if you want to extend query syntax, you need to define macros instead of regular functions.

    Something like the following should do the trick:

    defmacro downcase(field) do
      quote do
        fragment("downcase(?)", unquote(field))
      end
    end
    

    Remember you need to define macro before you use it.