Last active
August 28, 2021 04:55
-
-
Save hl/c535b594b24e858d0e5ccfff29280c7a to your computer and use it in GitHub Desktop.
Revisions
-
hl revised this gist
Jul 18, 2019 . 1 changed file with 26 additions and 26 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -79,8 +79,8 @@ defmodule Context do ## Examples iex> #{__MODULE__}.get_#{unquote(name)}(1) %#{unquote(schema)}{} """ @spec unquote(:"get_#{name}")(String.t()) :: unquote(schema).t() | nil def unquote(:"get_#{name}")(id) when is_binary(id) do @@ -102,8 +102,8 @@ defmodule Context do ## Examples iex> #{__MODULE__}.get_#{unquote(name)}!(1) %#{unquote(schema)}{} """ @spec unquote(:"get_#{name}!")(String.t()) :: unquote(schema).t() def unquote(:"get_#{name}!")(id) when is_binary(id) do @@ -125,8 +125,8 @@ defmodule Context do ## Examples iex> #{__MODULE__}.get_#{unquote(name)}_by(title: "title") %#{unquote(schema)}{} """ @spec unquote(:"get_#{name}_by")(keyword) :: unquote(schema).t() | nil def unquote(:"get_#{name}_by")(clauses) do @@ -148,8 +148,8 @@ defmodule Context do ## Examples iex> #{__MODULE__}.get_#{unquote(name)}_by!(title: "title") %#{unquote(schema)}{} """ @spec unquote(:"get_#{name}_by!")(keyword) :: unquote(schema).t() def unquote(:"get_#{name}_by!")(clauses) do @@ -171,8 +171,8 @@ defmodule Context do ## Examples iex> #{__MODULE__}.find_#{unquote(name)}(1) {:ok, %#{unquote(schema)}{}} """ @spec unquote(:"find_#{name}")(String.t()) :: {:ok, unquote(schema).t()} | {:error, {unquote(schema), :not_found}} @@ -198,8 +198,8 @@ defmodule Context do ## Examples iex> #{__MODULE__}.find_#{unquote(name)}_by(title: "title") {:ok, %#{unquote(schema)}{}} """ @spec unquote(:"find_#{name}_by")(keyword) :: {:ok, unquote(schema).t()} | {:error, {unquote(schema), :not_found}} @@ -225,8 +225,8 @@ defmodule Context do ## Examples iex> #{__MODULE__}.create_#{unquote(name)}(%{}) {:ok, %#{unquote(schema)}{}} """ @spec unquote(:"create_#{name}")(map) :: {:ok, unquote(schema).t()} | {:error, Ecto.Changeset.t()} @@ -250,8 +250,8 @@ defmodule Context do ## Examples iex> #{__MODULE__}.create_#{unquote(name)}(%{}) %#{unquote(schema)}{} """ @spec unquote(:"create_#{name}!")(map) :: unquote(schema).t() def unquote(:"create_#{name}!")(args) when is_map(args) do @@ -275,8 +275,8 @@ defmodule Context do ## Examples iex> #{__MODULE__}.update_#{unquote(name)}!(%#{unquote(schema)}{}, %{}) {:ok, %#{unquote(schema)}{}} """ @spec unquote(:"update_#{name}")(unquote(schema).t(), map) :: {:ok, unquote(schema).t()} | {:error, Ecto.Changeset.t()} @@ -308,8 +308,8 @@ defmodule Context do ## Examples iex> #{__MODULE__}.update_#{unquote(name)}!(%#{unquote(schema)}{}, %{}) %#{unquote(schema)}{} """ @spec unquote(:"update_#{name}!")(unquote(schema).t(), map) :: unquote(schema).t() def unquote(:"update_#{name}!")(%unquote(schema){} = struct, args) when is_map(args) do @@ -339,8 +339,8 @@ defmodule Context do ## Examples iex> #{__MODULE__}.delete_#{unquote(name)}(%#{unquote(name)}{}) {:ok, %#{unquote(schema)}{}} """ @spec unquote(:"delete_#{name}")(unquote(schema).t()) :: {:ok, unquote(schema).t()} | {:error, Ecto.Changeset.t()} @@ -363,8 +363,8 @@ defmodule Context do ## Examples iex> #{__MODULE__}.delete_#{unquote(name)}(%#{unquote(name)}{}) {:ok, %#{unquote(schema)}{}} """ @spec unquote(:"delete_#{name}!")(unquote(schema).t()) :: unquote(schema).t() def unquote(:"delete_#{name}!")(%unquote(schema){} = struct) do @@ -382,8 +382,8 @@ defmodule Context do ## Examples iex> #{__MODULE__}.change_#{unquote(name)}(%#{__MODULE__}{}, %{}) %Ecto.Changeset{} """ @spec unquote(:"change_#{name}")(map) :: Ecto.Changeset.t() def unquote(:"change_#{name}")(%unquote(schema){} = schema, args \\ %{}) do -
hl revised this gist
Jun 24, 2019 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -390,7 +390,7 @@ defmodule Context do unquote(schema).changeset(schema, args) end defoverridable [{unquote(:"change_#{name}"), 2}] end end end -
hl revised this gist
Jun 24, 2019 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -382,7 +382,7 @@ defmodule Context do ## Examples iex> #{__MODULE__}.change_#{unquote(name)}(%#{__MODULE__}{}, %{}) %Ecto.Changeset{} """ @spec unquote(:"change_#{name}")(map) :: Ecto.Changeset.t() -
hl revised this gist
Jun 24, 2019 . 1 changed file with 5 additions and 5 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -60,7 +60,7 @@ defmodule Context do {:"create_#{name}!", 1}, {:"update_#{name}!", 2}, {:"delete_#{name}!", 1}, {:"change_#{name}", 2} ] end @@ -375,19 +375,19 @@ defmodule Context do end end def gen_fun({:change, 2}, name, schema) do quote do @doc """ Returns an #{unquote(schema)} changeset ## Examples iex> #{__MODULE__}.change_#{unquote(name)}(#{__MODULE__}, %{}) %Ecto.Changeset{} """ @spec unquote(:"change_#{name}")(map) :: Ecto.Changeset.t() def unquote(:"change_#{name}")(%unquote(schema){} = schema, args \\ %{}) do unquote(schema).changeset(schema, args) end defoverridable [{unquote(:"change_#{name}"), 1}] -
hl revised this gist
Jun 22, 2019 . 1 changed file with 53 additions and 19 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -27,7 +27,7 @@ defmodule Context do end) end @spec parse_name(atom, any) :: String.t() defp parse_name(schema, caller) do schema |> Macro.expand_once(caller) @@ -37,15 +37,15 @@ defmodule Context do |> Macro.underscore() end @spec build_functions(String.t(), keyword) :: [{atom, non_neg_integer}] defp build_functions(name, opts) do only = Keyword.get(opts, :only, default_functions(name)) except = Keyword.get(opts, :except, []) only -- except end @spec default_functions(String.t()) :: [{atom, non_neg_integer}] defp default_functions(name) do [ {:"get_#{name}", 1}, @@ -59,12 +59,13 @@ defmodule Context do {:"delete_#{name}", 1}, {:"create_#{name}!", 1}, {:"update_#{name}!", 2}, {:"delete_#{name}!", 1}, {:"change_#{name}", 1} ] end @doc false @spec gen_fun(tuple, String.t(), atom) :: tuple def gen_fun(fun_and_arity, name, schema) def gen_fun({:get, 1}, name, schema) do @@ -81,8 +82,8 @@ defmodule Context do iex> #{__MODULE__}.get_#{unquote(name)}(1) %#{unquote(schema)}{} """ @spec unquote(:"get_#{name}")(String.t()) :: unquote(schema).t() | nil def unquote(:"get_#{name}")(id) when is_binary(id) do @__repo__.get(unquote(schema), id) end @@ -104,8 +105,8 @@ defmodule Context do iex> #{__MODULE__}.get_#{unquote(name)}!(1) %#{unquote(schema)}{} """ @spec unquote(:"get_#{name}!")(String.t()) :: unquote(schema).t() def unquote(:"get_#{name}!")(id) when is_binary(id) do @__repo__.get!(unquote(schema), id) end @@ -127,7 +128,7 @@ defmodule Context do iex> #{__MODULE__}.get_#{unquote(name)}_by(title: "title") %#{unquote(schema)}{} """ @spec unquote(:"get_#{name}_by")(keyword) :: unquote(schema).t() | nil def unquote(:"get_#{name}_by")(clauses) do @__repo__.get_by(unquote(schema), clauses) end @@ -150,7 +151,7 @@ defmodule Context do iex> #{__MODULE__}.get_#{unquote(name)}_by!(title: "title") %#{unquote(schema)}{} """ @spec unquote(:"get_#{name}_by!")(keyword) :: unquote(schema).t() def unquote(:"get_#{name}_by!")(clauses) do @__repo__.get_by!(unquote(schema), clauses) end @@ -173,9 +174,9 @@ defmodule Context do iex> #{__MODULE__}.find_#{unquote(name)}(1) {:ok, %#{unquote(schema)}{}} """ @spec unquote(:"find_#{name}")(String.t()) :: {:ok, unquote(schema).t()} | {:error, {unquote(schema), :not_found}} def unquote(:"find_#{name}")(id) when is_binary(id) do case @__repo__.get(unquote(schema), id) do nil -> {:error, {unquote(schema), :not_found}} term -> {:ok, term} @@ -200,7 +201,7 @@ defmodule Context do iex> #{__MODULE__}.find_#{unquote(name)}_by(title: "title") {:ok, %#{unquote(schema)}{}} """ @spec unquote(:"find_#{name}_by")(keyword) :: {:ok, unquote(schema).t()} | {:error, {unquote(schema), :not_found}} def unquote(:"find_#{name}_by")(clauses) do case @__repo__.get_by(unquote(schema), clauses) do @@ -227,7 +228,7 @@ defmodule Context do iex> #{__MODULE__}.create_#{unquote(name)}(%{}) {:ok, %#{unquote(schema)}{}} """ @spec unquote(:"create_#{name}")(map) :: {:ok, unquote(schema).t()} | {:error, Ecto.Changeset.t()} def unquote(:"create_#{name}")(args) when is_map(args) do changeset = unquote(schema).changeset(%unquote(schema){}, args) @@ -252,7 +253,7 @@ defmodule Context do iex> #{__MODULE__}.create_#{unquote(name)}(%{}) %#{unquote(schema)}{} """ @spec unquote(:"create_#{name}!")(map) :: unquote(schema).t() def unquote(:"create_#{name}!")(args) when is_map(args) do changeset = unquote(schema).changeset(%unquote(schema){}, args) @__repo__.insert!(changeset) @@ -277,10 +278,17 @@ defmodule Context do iex> #{__MODULE__}.update_#{unquote(name)}!(%#{unquote(schema)}{}, %{}) {:ok, %#{unquote(schema)}{}} """ @spec unquote(:"update_#{name}")(unquote(schema).t(), map) :: {:ok, unquote(schema).t()} | {:error, Ecto.Changeset.t()} def unquote(:"update_#{name}")(%unquote(schema){} = struct, args) when is_map(args) do struct = case Keyword.has_key?(unquote(schema).__info__(:functions), :preload) do true -> @__repo__.preload(struct, apply(unquote(schema), :preload, [])) false -> struct end changeset = unquote(schema).changeset(struct, args) @__repo__.update(changeset) end @@ -303,9 +311,16 @@ defmodule Context do iex> #{__MODULE__}.update_#{unquote(name)}!(%#{unquote(schema)}{}, %{}) %#{unquote(schema)}{} """ @spec unquote(:"update_#{name}!")(unquote(schema).t(), map) :: unquote(schema).t() def unquote(:"update_#{name}!")(%unquote(schema){} = struct, args) when is_map(args) do struct = case Keyword.has_key?(unquote(schema).__info__(:functions), :preload) do true -> @__repo__.preload(struct, apply(unquote(schema), :preload, [])) false -> struct end changeset = unquote(schema).changeset(struct, args) @__repo__.update!(changeset) end @@ -359,4 +374,23 @@ defmodule Context do defoverridable [{unquote(:"delete_#{name}!"), 1}] end end def gen_fun({:change, 1}, name, schema) do quote do @doc """ Returns an #{unquote(schema)} changeset ## Examples iex> #{__MODULE__}.change_#{unquote(name)}(%{}) %Ecto.Changeset{} """ @spec unquote(:"change_#{name}")(map) :: Ecto.Changeset.t() def unquote(:"change_#{name}")(args \\ %{}) do unquote(schema).changeset(%unquote(schema){}, args) end defoverridable [{unquote(:"change_#{name}"), 1}] end end end -
hl created this gist
Jun 19, 2019 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,362 @@ defmodule Context do @moduledoc false defmacro __using__(opts) do repo = Keyword.fetch!(opts, :repo) quote do import Context, only: [context: 1, context: 2] Module.put_attribute(__MODULE__, :__repo__, unquote(repo)) end end @doc false defmacro context(schema, opts \\ []) do name = Keyword.get(opts, :name, parse_name(schema, __CALLER__)) funs = build_functions(name, opts) Enum.reduce(funs, [], fn {fun_name, arity}, acc -> fun = fun_name |> Atom.to_string() |> String.replace("_#{name}", "") |> String.to_existing_atom() [Kernel.apply(__MODULE__, :gen_fun, [{fun, arity}, name, schema]) | acc] end) end @spec parse_name(atom(), any()) :: String.t() defp parse_name(schema, caller) do schema |> Macro.expand_once(caller) |> Atom.to_string() |> String.split(".") |> List.last() |> Macro.underscore() end @spec build_functions(String.t(), keyword()) :: [{atom(), non_neg_integer()}] defp build_functions(name, opts) do only = Keyword.get(opts, :only, default_functions(name)) except = Keyword.get(opts, :except, []) only -- except end @spec default_functions(String.t()) :: [{atom(), non_neg_integer()}] defp default_functions(name) do [ {:"get_#{name}", 1}, {:"get_#{name}!", 1}, {:"get_#{name}_by", 1}, {:"get_#{name}_by!", 1}, {:"find_#{name}", 1}, {:"find_#{name}_by", 1}, {:"create_#{name}", 1}, {:"update_#{name}", 2}, {:"delete_#{name}", 1}, {:"create_#{name}!", 1}, {:"update_#{name}!", 2}, {:"delete_#{name}!", 1} ] end @doc false @spec gen_fun(tuple(), String.t(), atom()) :: tuple() def gen_fun(fun_and_arity, name, schema) def gen_fun({:get, 1}, name, schema) do quote do @doc """ Get a #{unquote(schema)} by ID ## Parameters - id: Valid ID ## Examples iex> #{__MODULE__}.get_#{unquote(name)}(1) %#{unquote(schema)}{} """ @spec unquote(:"get_#{name}")(integer()) :: unquote(schema).t() | nil def unquote(:"get_#{name}")(id) do @__repo__.get(unquote(schema), id) end defoverridable [{unquote(:"get_#{name}"), 1}] end end def gen_fun({:get!, 1}, name, schema) do quote do @doc """ Find a #{unquote(schema)} by ID ## Parameters - id: Valid ID ## Examples iex> #{__MODULE__}.get_#{unquote(name)}!(1) %#{unquote(schema)}{} """ @spec unquote(:"get_#{name}!")(integer()) :: unquote(schema).t() def unquote(:"get_#{name}!")(id) do @__repo__.get!(unquote(schema), id) end defoverridable [{unquote(:"get_#{name}!"), 1}] end end def gen_fun({:get_by, 1}, name, schema) do quote do @doc """ Find a #{unquote(schema)} by clauses ## Parameters - clauses: keyword list ## Examples iex> #{__MODULE__}.get_#{unquote(name)}_by(title: "title") %#{unquote(schema)}{} """ @spec unquote(:"get_#{name}_by")(keyword()) :: unquote(schema).t() | nil def unquote(:"get_#{name}_by")(clauses) do @__repo__.get_by(unquote(schema), clauses) end defoverridable [{unquote(:"get_#{name}_by"), 1}] end end def gen_fun({:get_by!, 1}, name, schema) do quote do @doc """ Find a #{unquote(schema)} by clauses ## Parameters - clauses: keyword list ## Examples iex> #{__MODULE__}.get_#{unquote(name)}_by!(title: "title") %#{unquote(schema)}{} """ @spec unquote(:"get_#{name}_by!")(keyword()) :: unquote(schema).t() def unquote(:"get_#{name}_by!")(clauses) do @__repo__.get_by!(unquote(schema), clauses) end defoverridable [{unquote(:"get_#{name}_by!"), 1}] end end def gen_fun({:find, 1}, name, schema) do quote do @doc """ Find a #{unquote(schema)} by ID ## Parameters - id: Valid ID ## Examples iex> #{__MODULE__}.find_#{unquote(name)}(1) {:ok, %#{unquote(schema)}{}} """ @spec unquote(:"find_#{name}")(integer()) :: {:ok, unquote(schema).t()} | {:error, {unquote(schema), :not_found}} def unquote(:"find_#{name}")(id) do case @__repo__.get(unquote(schema), id) do nil -> {:error, {unquote(schema), :not_found}} term -> {:ok, term} end end defoverridable [{unquote(:"find_#{name}"), 1}] end end def gen_fun({:find_by, 1}, name, schema) do quote do @doc """ Find a #{unquote(schema)} by clauses ## Parameters - clauses: keyword list ## Examples iex> #{__MODULE__}.find_#{unquote(name)}_by(title: "title") {:ok, %#{unquote(schema)}{}} """ @spec unquote(:"find_#{name}_by")(keyword()) :: {:ok, unquote(schema).t()} | {:error, {unquote(schema), :not_found}} def unquote(:"find_#{name}_by")(clauses) do case @__repo__.get_by(unquote(schema), clauses) do nil -> {:error, {unquote(schema), :not_found}} term -> {:ok, term} end end defoverridable [{unquote(:"find_#{name}_by"), 1}] end end def gen_fun({:create, 1}, name, schema) do quote do @doc """ Create a new #{unquote(schema)} ## Parameters - args: map ## Examples iex> #{__MODULE__}.create_#{unquote(name)}(%{}) {:ok, %#{unquote(schema)}{}} """ @spec unquote(:"create_#{name}")(map()) :: {:ok, unquote(schema).t()} | {:error, Ecto.Changeset.t()} def unquote(:"create_#{name}")(args) when is_map(args) do changeset = unquote(schema).changeset(%unquote(schema){}, args) @__repo__.insert(changeset) end defoverridable [{unquote(:"create_#{name}"), 1}] end end def gen_fun({:create!, 1}, name, schema) do quote do @doc """ Create a new #{unquote(schema)} ## Parameters - args: map ## Examples iex> #{__MODULE__}.create_#{unquote(name)}(%{}) %#{unquote(schema)}{} """ @spec unquote(:"create_#{name}!")(map()) :: unquote(schema).t() def unquote(:"create_#{name}!")(args) when is_map(args) do changeset = unquote(schema).changeset(%unquote(schema){}, args) @__repo__.insert!(changeset) end defoverridable [{unquote(:"create_#{name}!"), 1}] end end def gen_fun({:update, 2}, name, schema) do quote do @doc """ Update an existing #{unquote(schema)} ## Parameters - struct: %#{unquote(schema)}{} - args: map ## Examples iex> #{__MODULE__}.update_#{unquote(name)}!(%#{unquote(schema)}{}, %{}) {:ok, %#{unquote(schema)}{}} """ @spec unquote(:"update_#{name}")(unquote(schema).t(), map()) :: {:ok, unquote(schema).t()} | {:error, Ecto.Changeset.t()} def unquote(:"update_#{name}")(%unquote(schema){} = struct, args) when is_map(args) do changeset = unquote(schema).changeset(struct, args) @__repo__.update(changeset) end defoverridable [{unquote(:"update_#{name}"), 2}] end end def gen_fun({:update!, 2}, name, schema) do quote do @doc """ Update an existing #{unquote(schema)} ## Parameters - struct: %#{unquote(schema)}{} - args: map ## Examples iex> #{__MODULE__}.update_#{unquote(name)}!(%#{unquote(schema)}{}, %{}) %#{unquote(schema)}{} """ @spec unquote(:"update_#{name}!")(unquote(schema).t(), map()) :: unquote(schema).t() def unquote(:"update_#{name}!")(%unquote(schema){} = struct, args) when is_map(args) do changeset = unquote(schema).changeset(struct, args) @__repo__.update!(changeset) end defoverridable [{unquote(:"update_#{name}!"), 2}] end end def gen_fun({:delete, 1}, name, schema) do quote do @doc """ Delete an existing #{unquote(schema)} ## Parameters - struct: %#{unquote(schema)}{} ## Examples iex> #{__MODULE__}.delete_#{unquote(name)}(%#{unquote(name)}{}) {:ok, %#{unquote(schema)}{}} """ @spec unquote(:"delete_#{name}")(unquote(schema).t()) :: {:ok, unquote(schema).t()} | {:error, Ecto.Changeset.t()} def unquote(:"delete_#{name}")(%unquote(schema){} = struct) do @__repo__.delete(struct) end defoverridable [{unquote(:"delete_#{name}"), 1}] end end def gen_fun({:delete!, 1}, name, schema) do quote do @doc """ Delete an existing #{unquote(schema)} ## Parameters - struct: %#{unquote(schema)}{} ## Examples iex> #{__MODULE__}.delete_#{unquote(name)}(%#{unquote(name)}{}) {:ok, %#{unquote(schema)}{}} """ @spec unquote(:"delete_#{name}!")(unquote(schema).t()) :: unquote(schema).t() def unquote(:"delete_#{name}!")(%unquote(schema){} = struct) do @__repo__.delete(struct) end defoverridable [{unquote(:"delete_#{name}!"), 1}] end end end