defmodule Mix.Tasks.Phx.Gen.Solid.Value do
@shortdoc "Generates Value logic for a resource"
@moduledoc """
Generates Value logic for a resource.
mix phx.gen.solid.value Accounts User users id name age
The first argument is the context module followed by the schema module and its
plural name.
This creates a new Value in `MyApp.Accounts.Value.User`. By default the
allowed fields for this value will be the arguments you passed into the
generator, in this case, `@valid_fields [:id, :slug, :name]`.
**Options**
- `--helpers` - This will generate the Value helpers context in `MyApp.Value`.
Module name can be overridden by `--value-context`.
- `--value-context MODULE` - This will be the name used for the helpers alias
and/or helper modue name when generated. Defaults to `MyApp.Value`.
The generated Value relies on a few helper functions also generated by this
task. By default it will be placed in your projects context folder.
For more information about the generated Value, see the [Overview](overview.html).
"""
use Mix.Task
alias Mix.Phoenix.Context
alias Mix.Tasks.Phx.Gen
alias PhxGenSolid.Generator
@switches [helpers: :boolean, value_context: :string]
@impl true
def run(args) do
if Mix.Project.umbrella?() do
Mix.raise("mix phx.gen.solid can only be run inside an application directory")
end
{opts, parsed} = OptionParser.parse!(args, strict: @switches)
# Don't pass along the opts
{context, schema} = Gen.Context.build(parsed, __MODULE__)
binding = [
context: context,
opts: opts,
schema: schema,
web_app_name: Generator.web_app_name(context),
value_context: build_value_context(context, opts),
value_fields: build_value_fields(schema.attrs),
value_module:
Module.concat([
context.base_module,
"#{inspect(context.alias)}",
"Value",
"#{inspect(schema.alias)}"
])
]
paths = Generator.paths()
Generator.prompt_for_conflicts(context, &files_to_be_generated/2, opts)
Generator.copy_new_files(context, binding, paths, &files_to_be_generated/2, opts)
end
def raise_with_help(msg), do: Generator.raise_with_help(msg)
defp build_value_context(context, opts) do
default_context = Module.concat([context.base_module, "Value"])
case Keyword.has_key?(opts, :value_context) do
true ->
opts
|> Keyword.get(:value_context)
|> String.split(".")
|> Module.concat()
false ->
default_context
end
end
defp files_to_be_generated(%Context{schema: schema} = context, opts) do
should_gen_helpers = Keyword.get(opts, :helpers, false)
base_files = [
{:eex, "value.ex", Path.join([context.dir, "values", "#{schema.singular}.ex"])}
]
helpers = helper_files_to_be_generated(context)
maybe_gen_helpers(base_files, helpers, should_gen_helpers)
end
defp helper_files_to_be_generated(%Context{context_app: context_app}) do
app_path = Mix.Phoenix.context_lib_path(context_app, "")
[
{:eex, "value_context.ex", Path.join([app_path, "value.ex"])}
]
end
defp maybe_gen_helpers(base_files, helpers, true), do: Enum.concat(base_files, helpers)
defp maybe_gen_helpers(base_files, _helpers, false), do: base_files
defp build_value_fields(attrs) do
Keyword.keys(attrs)
end
end