Skip to content

Commit

Permalink
Allow using sigils/attributes in map/struct selects
Browse files Browse the repository at this point in the history
  • Loading branch information
michalmuskala committed Nov 19, 2016
1 parent 2e9e0af commit 7368546
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 14 deletions.
33 changes: 19 additions & 14 deletions lib/ecto/query/builder/select.ex
Original file line number Diff line number Diff line change
Expand Up @@ -67,21 +67,11 @@ defmodule Ecto.Query.Builder.Select do
end

# map/struct(var, [:foo, :bar])
defp escape({tag, _, [{var, _, context}, fields]}, {params, take}, vars, _env)
defp escape({tag, _, [{var, _, context}, fields]}, {params, take}, vars, env)
when tag in [:map, :struct] and is_atom(var) and is_atom(context) do
taken =
case fields do
{:^, _, [interpolated]} ->
quote(do: Ecto.Query.Builder.Select.fields!(unquote(tag), unquote(interpolated)))
_ when is_list(fields) ->
fields
true ->
Builder.error! "`#{tag}/2` in `select` expects either a literal or "
"an interpolated list of atom fields"
end

expr = Builder.escape_var(var, vars)
take = Map.put(take, Builder.find_var!(var, vars), {tag, taken})
taken = escape_fields(fields, tag, env)
expr = Builder.escape_var(var, vars)
take = Map.put(take, Builder.find_var!(var, vars), {tag, taken})
{expr, {params, take}}
end

Expand Down Expand Up @@ -112,6 +102,21 @@ defmodule Ecto.Query.Builder.Select do
escape(k, params_take, vars, env)
end

defp escape_fields({:^, _, [interpolated]}, tag, _env) do
quote do
Ecto.Query.Builder.Select.fields!(unquote(tag), unquote(interpolated))
end
end
defp escape_fields(expr, tag, env) do
case Macro.expand(expr, env) do
fields when is_list(fields) ->
fields
_ ->
Builder.error! "`#{tag}/2` in `select` expects either a literal or " <>
"an interpolated list of atom fields"
end
end

@doc """
Called at runtime to verify a field.
"""
Expand Down
8 changes: 8 additions & 0 deletions test/ecto/query/builder/select_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,12 @@ defmodule Ecto.Query.Builder.SelectTest do
assert select("q", [q], map(q, ^fields)).select.take == %{0 => {:map, fields}}
assert select("q", [q], struct(q, ^fields)).select.take == %{0 => {:struct, fields}}
end

@fields [:field]

test "select sigil/attribute" do
fields = ~w[field]a
assert select("q", [q], map(q, ~w[field]a)).select.take == %{0 => {:map, fields}}
assert select("q", [q], struct(q, @fields)).select.take == %{0 => {:struct, fields}}
end
end

0 comments on commit 7368546

Please sign in to comment.