Ecto join on dynamic fields

Hi there !

I’d like to reduce the amount of joins in my code.

Instead of having, let’s say:

  def join_on_client_id_and_id(from, query) do
    from c in ^from,
      join: q in ^query,
      on: c.client_id == q.id
  end

and another function like this:

  def join_on_client_id_and_client_id(from, query) do
    from c in ^from,
      join: q in ^query,
      on: c.client_id == q.client_id
  end

instead, I would like to have a function with that signature:
def join_on_client(from, query, options \\ [with: :client_id]) with with being the field on ^query to join on.
I would for instance use send(m, options[:with] to specify the second field to join on.

I’ve found out that I could maybe use the Ecto.Query.dynamic function but can’t find a good example on how to use it in the case of a join.

Could you please help me ?

Actually, nevermind!

It seems that the function Ecto.Query.field does the trick :

  def join(from, query, options \\ [with: :client_id]) do
    join_field = options[:with]
    from c in from,
      join: q in ^query,
      on: c.client_id == field(q, ^join_field)
  end

May this help someone else :slight_smile:

3 Likes