Current section
Files
Jump to
Current section
Files
lib/elixir_scribe.ex
defmodule ElixirScribe do
@moduledoc """
The Elixir Scribe Generator configuration and defaults.
Some of the defaults will be possible to customize via your app configuration:
* [Configure Default Resource Actions](#module-configure-default-resource-actions) - Provide your own list of built-in default actions that will be used each time you invoke one of the generators.
* [Configure Default Resource Actions Aliases](#module-configure-resource-actions-aliases) - Use aliases to rename the built-in default actions to your preferred names.
* [Configure Default Source Code Templates](#module-configure-default-source-code-templates) - Provide your own source code templates to be used by the Elixir Scribe generators
> #### Private Module {: .warning}
> All functions in this module lack documentation because they **MUST** be considered private and used internally only.
## Configure Default Resource Actions
The default actions supported by `scribe.gen.domain` and `scribe.gen.html`:
* `list` - Lists all items of a Resource in the database
* `new` - Builds a new changeset for a Resource
* `read` - Reads a specific Resource from the database
* `edit` - Builds a changeset to track changes made to a Resource
* `create` - Creates a new Resource in the database
* `update` - Updates an existing Resource
* `delete` - Deletes an existing Resource
For example, for an API you can discard the default resource actions `new` and `edit`:
```elixir
config :elixir_scribe,
default_resource_actions: ["list", "read", "create", "update", "delete"]
```
Or, maybe you want to use the default resource actions, plus some other ones that you always need when creating a new resource:
```elixir
config :elixir_scribe,
default_resource_actions: ["import", "export", "list", "new", "read", "edit", "create", "update", "delete"]
```
> #### Custom Resource Actions Order {: .error}
> Order of actions **MATTERS**, otherwise routes will not work as expected.
>
> Note how `import` and `export` were added to the begin of the list to ensure they are matched correctly by the router when serving the `GET` request.
> #### Custom Resource Actions {: .warning}
> Any custom action name provided via the configuration will be mapped to a default template, unless you provide your custom template(s) for it at the correct path in your app `priv/templates/*`. Check how to customize the templates at [Configure Default Source Code Templates](#module-configure-default-source-code-templates).
>
> This custom action names will be added to your router as `GET` requests. You need to customize the router as needed.
## Configure Resource Actions Aliases
In your app configuration for `:elixir_scribe` you can map any of the built-in default actions to actions names of your preference, which it's the same as renaming them.
The below example maps the built-in default actions `read` to `show` and `list` to `index`.
```elixir
config :elixir_scribe,
resource_actions_aliases: %{
"read" => "show",
"list" => "index",
}
```
## Configure Default Source Code Templates
The paths to look for template files for generators defaults to checking the current app's `priv` directory, and falls back to Elixir Scribe and Phoenix's `priv` directory:
* `priv/templates/*`
* `elixir_scribe/priv/templates/*`
* `phoenix/priv/templates/*`
Provide your own templates to customize the functionality offered by the built-in ones by copying them to your `priv/templates/*` directory, and then modify them as you see fit.
For example, when using custom resource actions, the Elixir Scribe generators will default to generating code that raises an error with a message alerting you that the logic hasn’t been implemented yet. You can avoid this by providing your own custom source code template for each of your custom actions.
"""
@doc false
def base_template_paths(), do: [".", :elixir_scribe, :phoenix]
@doc false
def app_name() do
Mix.Project.config() |> Keyword.get(:app) |> Atom.to_string()
end
@doc false
def app_path(:lib_core), do: Path.join(["lib", app_name()])
@doc false
def app_path(:test_core), do: Path.join(["test", app_name()])
@doc false
def app_path(:lib_web), do: app_path(:lib_core) <> "_web"
@doc false
def app_path(:test_web), do: app_path(:test_core) <> "_web"
@web_template_path "priv/templates/scribe.gen.html"
@doc false
def web_template_path(), do: @web_template_path
@html_template_path @web_template_path |> Path.join("html")
@doc false
def html_template_path(), do: @html_template_path
@controller_template_path @web_template_path |> Path.join("controllers")
@doc false
def controller_template_path(), do: @controller_template_path
@controller_test_template_path Path.join([@web_template_path, "tests", "controllers"])
@doc false
def controller_test_template_path(), do: @controller_test_template_path
@domain_template_path "priv/templates/scribe.gen.domain"
@doc false
def domain_template_path(), do: @domain_template_path
@domain_tests_template_path @domain_template_path |> Path.join("tests")
@doc false
def domain_tests_template_path(), do: @domain_tests_template_path
@domain_api_template_path @domain_template_path |> Path.join("apis")
@doc false
def domain_api_template_path(), do: @domain_api_template_path
@resource_actions_template_path @domain_template_path |> Path.join("actions")
@doc false
def resource_actions_template_path(), do: @resource_actions_template_path
@resource_test_actions_template_path @domain_tests_template_path |> Path.join("actions")
@doc false
def resource_test_actions_template_path(), do: @resource_test_actions_template_path
# @IMPORTANT: Order of actions MATTERS, otherwise routes will not work as
# expected. Don't allow override from config, but allow to set aliases.
@default_resource_actions ["list", "new", "read", "edit", "create", "update", "delete"]
@doc false
def resource_actions() do
Application.get_env(:elixir_scribe, :default_resource_actions, @default_resource_actions)
end
@doc false
def resource_actions_aliases() do
Application.get_env(:elixir_scribe, :resource_actions_aliases, %{})
end
@doc false
def resource_action_alias(action) do
resource_actions_aliases() |> Map.get(action, action)
end
@resource_html_actions ["read", "new", "edit", "list"]
@doc false
def resource_html_actions() do
Application.get_env(:elixir_scribe, :resource_html_actions, @resource_html_actions)
end
@resource_plural_actions ["index", "list"]
@doc false
def resource_plural_actions() do
Application.get_env(:elixir_scribe, :resource_plural_actions, @resource_plural_actions)
end
@doc false
def schema_template_folder_name(%ElixirScribe.Generator.SchemaContract{} = schema) do
if schema.generate? do
"schema_access"
else
"no_schema_access"
end
end
@app_file_extensions [".ex", ".exs", "html.heex"]
@doc false
def app_file_extensions(), do: @app_file_extensions
@app_file_types ["", "controller", "controller_test", "test"]
@doc false
def app_file_types(), do: @app_file_types
@app_path_types [:lib_core, :lib_web, :test_core, :test_web]
@doc false
def app_path_types(), do: @app_path_types
# @TODO Remove once `mix phx.gem.schema` is ported to `mix scribe.gen.schema`.
@doc false
def to_phoenix_schema(%ElixirScribe.Generator.SchemaContract{} = schema) do
attrs = Map.from_struct(schema)
struct(Mix.Phoenix.Schema, attrs)
end
end