Packages

A way to increase Elixir projects readability and maintenance based on Use Cases and Interactors.

Current section

Files

Jump to
use_case lib mix tasks use_case.gen.phx_resources_html.ex
Raw

lib/mix/tasks/use_case.gen.phx_resources_html.ex

defmodule Mix.Tasks.UseCase.Gen.PhxResourceHtml do
@shortdoc "Generates repo, schema, migration, controllers, html templates, views and tests for a resource"
@moduledoc """
Generates repo, schema, migration, controllers, html templates, views and tests for a resource.
mix use_case.gen.phx_resource Post posts title content image likes:int
or
mix use_case.gen.phx_resource Post posts title content image likes:int --context MyBoundedContext
The first argument is the resource name, the second the database table name for the resource and the others the resource fields. We can set the --context flag to create the resource in context folders and namespaces
"""
use Mix.Task
alias UcScaffold.Mix.Phoenix.Schema
def run(io_puts \\ true, args_and_options) do
if io_puts do
IO.puts("""
use_case.gen.phx_resource_html ->
""")
end
{options, args, []} = OptionParser.parse(args_and_options, strict: [context: :string])
option_context = get_option_context(Keyword.get(options, :context, nil))
context = get_context(args)
table_name = get_table_name(args)
schema_name = get_schema_name(args, option_context)
schema_fields = get_schema_fields(args)
schema = Schema.new(schema_name, table_name, schema_fields, [])
create_controller(context, schema, option_context)
create_controller_test(context, schema, option_context)
create_view(context, schema, option_context)
create_edit_html(context, schema, option_context)
create_form_html(context, schema, option_context)
create_index_html(context, schema, option_context)
create_new_html(context, schema, option_context)
create_show_html(context, schema, option_context)
Mix.Tasks.UseCase.Gen.PhxResource.run(false, args_and_options)
end
defp create_controller(context, schema, option_context) do
updated_alias =
schema.alias
|> Atom.to_string()
|> String.replace("Elixir.", "")
updated_module =
schema.module
|> Atom.to_string()
|> String.replace("Elixir.", "")
path =
if Keyword.get(option_context, :path, false) do
"lib/#{context[:web_path]}/controllers/#{option_context[:path]}/#{context[:path]}_controller.ex"
else
"lib/#{context[:web_path]}/controllers/#{context[:path]}_controller.ex"
end
copy_template("controller.eex", path,
context: context,
option_context: option_context,
schema: Map.merge(schema, %{alias: updated_alias, module: updated_module})
)
end
defp create_controller_test(context, schema, option_context) do
updated_alias =
schema.alias
|> Atom.to_string()
|> String.replace("Elixir.", "")
path =
if Keyword.get(option_context, :path, false) do
"test/#{context[:web_path]}/controllers/#{option_context[:path]}/#{context[:path]}_controller_test.ex"
else
"test/#{context[:web_path]}/controllers/#{context[:path]}_controller_test.ex"
end
copy_template("controller_test.eex", path,
context: context,
option_context: option_context,
schema: Map.merge(schema, %{alias: updated_alias})
)
end
defp create_view(context, schema, option_context) do
path =
if Keyword.get(option_context, :path, false) do
"lib/#{context[:web_path]}/views/#{option_context[:path]}/#{context[:path]}_view.ex"
else
"lib/#{context[:web_path]}/views/#{context[:path]}_view.ex"
end
copy_template("view.eex", path,
context: context,
option_context: option_context,
schema: schema
)
end
defp create_edit_html(context, schema, option_context) do
path =
if Keyword.get(option_context, :path, false) do
"lib/#{context[:web_path]}/templates/#{option_context[:path]}/#{context[:path]}/edit.html.eex"
else
"lib/#{context[:web_path]}/templates/#{context[:path]}/edit.html.eex"
end
copy_template("edit.html.eex", path,
schema: schema
)
end
defp create_form_html(context, schema, option_context) do
path =
if Keyword.get(option_context, :path, false) do
"lib/#{context[:web_path]}/templates/#{option_context[:path]}/#{context[:path]}/form.html.eex"
else
"lib/#{context[:web_path]}/templates/#{context[:path]}/form.html.eex"
end
copy_template("form.html.eex", path,
schema: schema,
inputs: inputs(schema)
)
end
defp create_index_html(context, schema, option_context) do
path =
if Keyword.get(option_context, :path, false) do
"lib/#{context[:web_path]}/templates/#{option_context[:path]}/#{context[:path]}/index.html.eex"
else
"lib/#{context[:web_path]}/templates/#{context[:path]}/index.html.eex"
end
copy_template("index.html.eex", path,
schema: schema
)
end
defp create_new_html(context, schema, option_context) do
path =
if Keyword.get(option_context, :path, false) do
"lib/#{context[:web_path]}/templates/#{option_context[:path]}/#{context[:path]}/new.html.eex"
else
"lib/#{context[:web_path]}/templates/#{context[:path]}/new.html.eex"
end
copy_template("new.html.eex", path,
schema: schema
)
end
defp create_show_html(context, schema, option_context) do
path =
if Keyword.get(option_context, :path, false) do
"lib/#{context[:web_path]}/templates/#{option_context[:path]}/#{context[:path]}/show.html.eex"
else
"lib/#{context[:web_path]}/templates/#{context[:path]}/show.html.eex"
end
copy_template("show.html.eex", path,
schema: schema
)
end
defp copy_template(name, final_path, opts) do
Path.join(:code.priv_dir(:use_case), "templates/use_case.gen.phx_resource_html/#{name}")
|> Mix.Generator.copy_template(final_path, opts)
end
defp get_table_name([_,table_name|_]) do
table_name
end
defp get_schema_name([schema|_], []) do
"Schemas.#{schema}"
end
defp get_schema_name([schema|_], option_context) do
option_context[:scoped] <> ".Schemas.#{schema}"
end
defp get_schema_fields([_,_|schema_fields]) do
schema_fields
end
defp get_context([schema_name|_]) do
call_phoenix_inflector(schema_name)
end
defp get_context(_) do
raise "Schema name is obrigatory"
end
defp get_option_context(nil), do: []
defp get_option_context(name) do
call_phoenix_inflector(name)
end
defp call_phoenix_inflector(name) do
UcScaffold.Mix.Phoenix.Inflector.call(name)
end
defp inputs(%Schema{} = schema) do
Enum.map(schema.attrs, fn
{_, {:references, _}} ->
{nil, nil, nil}
{key, :integer} ->
{label(key), ~s(<%= number_input f, #{inspect(key)} %>), error(key)}
{key, :float} ->
{label(key), ~s(<%= number_input f, #{inspect(key)}, step: "any" %>), error(key)}
{key, :decimal} ->
{label(key), ~s(<%= number_input f, #{inspect(key)}, step: "any" %>), error(key)}
{key, :boolean} ->
{label(key), ~s(<%= checkbox f, #{inspect(key)} %>), error(key)}
{key, :text} ->
{label(key), ~s(<%= textarea f, #{inspect(key)} %>), error(key)}
{key, :date} ->
{label(key), ~s(<%= date_select f, #{inspect(key)} %>), error(key)}
{key, :time} ->
{label(key), ~s(<%= time_select f, #{inspect(key)} %>), error(key)}
{key, :utc_datetime} ->
{label(key), ~s(<%= datetime_select f, #{inspect(key)} %>), error(key)}
{key, :naive_datetime} ->
{label(key), ~s(<%= datetime_select f, #{inspect(key)} %>), error(key)}
{key, {:array, :integer}} ->
{label(key), ~s(<%= multiple_select f, #{inspect(key)}, ["1": 1, "2": 2] %>), error(key)}
{key, {:array, _}} ->
{label(key), ~s(<%= multiple_select f, #{inspect(key)}, ["Option 1": "option1", "Option 2": "option2"] %>), error(key)}
{key, _} ->
{label(key), ~s(<%= text_input f, #{inspect(key)} %>), error(key)}
end)
end
defp label(key) do
~s(<%= label f, #{inspect(key)} %>)
end
defp error(field) do
~s(<%= error_tag f, #{inspect(field)} %>)
end
end