cjm2671
cjm2671

Reputation: 19486

Conditional parameters in an Ecto Query

I've got a parameter platform which is optional:

def query_clicks(freq \\ "day", platform \\ false) do
    from(Click)
    |> select(
      [c],
      [
        fragment("date_trunc(?,?) as t", ^freq, c.inserted_at), count(c.link_id) ]
      )
      |> if platform, do: fn(q) -> where([c], c.platform == ^platform) end, else: fn(q): q end
    |> group_by([c], fragment("t"))
    |> Repo.all
  end

I've tried to hack something in (see "if platform..."), but I'm not sure of the exact syntax to use. What I want to do is:

if platform != None:
  return query + WHERE statement
else:
  return query

What's the right syntax?

Upvotes: 2

Views: 2102

Answers (2)

Meysam Feghhi
Meysam Feghhi

Reputation: 945

This might be too late but I just wanted to share my solution to this problem. Make use of the fact that piping a queryable through any method of Ecto macro api such as where, select, limit, offset etc. still returns a queryable. so it can be done by a simple if:

def query_clicks(freq \\ "day", platform \\ false) do
  query = from(Click) |> select(...)

  (if platform, do: where(query, [c], c.platform == ^platform), else: query)
  |> group_by([c], fragment("t"))
  |> Repo.all
end

Its less code. Hope it helps :)

Upvotes: 0

Maarten van Vliet
Maarten van Vliet

Reputation: 592

You could add an extra function maybe_platform/2

defp maybe_platform(queryable, nil), do: queryable
defp maybe_platform(queryable, platform) do
  queryable
  |> where([c], c.platform == ^platform)
end

Then your query_clicks/2 looks like

def query_clicks(freq \\ "day", platform \\ false) do
  from(Click)
  |> select(
    [c],
    [
      fragment("date_trunc(?,?) as t", ^freq, c.inserted_at), count(c.link_id) 
    ]
  )
  |> maybe_platform(platform)
  |> group_by([c], fragment("t"))
  |> Repo.all
end

It can be done in a anonymous function like you did but this is a little clearer imo.

Upvotes: 1

Related Questions