Skip to content

Commit

Permalink
feat: mix ash_postgres.gen.resources
Browse files Browse the repository at this point in the history
  • Loading branch information
zachdaniel committed Sep 5, 2024
1 parent 133be50 commit efa4ef0
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 28 deletions.
5 changes: 4 additions & 1 deletion lib/mix/tasks/ash_postgres.gen.resources.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ defmodule Mix.Tasks.AshPostgres.Gen.Resources do
- `tables`, `t` - Defaults to `public.*`. The tables to generate resources for, comma separated. Can be specified multiple times. See the section on tables for more.
- `skip-tables`, `s` - The tables to skip generating resources for, comma separated. Can be specified multiple times. See the section on tables for more.
- `snapshots-only` - Only generate snapshots for the generated resources, and not migraitons.
- `yes`, `y` - Answer yes (or skip) to all questions.
## Tables
Expand All @@ -41,13 +42,15 @@ defmodule Mix.Tasks.AshPostgres.Gen.Resources do
example: @example,
schema: [
repo: :keep,
yes: :boolean,
tables: :keep,
skip_tables: :keep,
snapshots_only: :boolean,
domain: :keep
],
aliases: [
t: :tables,
y: :boolean,
r: :repo,
d: :domain,
s: :skip_tables
Expand Down Expand Up @@ -109,7 +112,7 @@ defmodule Mix.Tasks.AshPostgres.Gen.Resources do
"""

options =
if Mix.shell().yes?(prompt) do
if options[:yes] || Mix.shell().yes?(prompt) do
Keyword.put(options, :no_migrations, false)
else
Keyword.put(options, :no_migrations, true)
Expand Down
2 changes: 1 addition & 1 deletion lib/resource_generator/resource_generator.ex
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ defmodule AshPostgres.ResourceGenerator do
with `--tables` or `--skip-tables`
"""
end)
|> Spec.add_relationships(resources)
|> Spec.add_relationships(resources, opts)

Enum.reduce(specs, igniter, fn table_spec, igniter ->
table_to_resource(igniter, table_spec, domain, opts)
Expand Down
62 changes: 36 additions & 26 deletions lib/resource_generator/spec.ex
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ defmodule AshPostgres.ResourceGenerator.Spec do
}
end)
|> Enum.map(fn {[table_name, table_schema], attributes} ->
attributes = build_attributes(attributes, table_name, table_schema, repo)
attributes = build_attributes(attributes, table_name, table_schema, repo, opts)

%__MODULE__{
table_name: table_name,
Expand Down Expand Up @@ -454,11 +454,11 @@ defmodule AshPostgres.ResourceGenerator.Spec do
end
end

defp build_attributes(attributes, table_name, schema, repo) do
defp build_attributes(attributes, table_name, schema, repo, opts) do
attributes
|> set_primary_key(table_name, schema, repo)
|> set_sensitive()
|> set_types()
|> set_types(opts)
|> set_defaults_and_generated()
end

Expand Down Expand Up @@ -540,7 +540,7 @@ defmodule AshPostgres.ResourceGenerator.Spec do
end)
end

def add_relationships(specs, resources) do
def add_relationships(specs, resources, opts) do
specs
|> Enum.group_by(& &1.repo)
|> Enum.flat_map(fn {repo, specs} ->
Expand All @@ -552,12 +552,13 @@ defmodule AshPostgres.ResourceGenerator.Spec do
else
[]
end
end)
end),
opts
)
end)
end

defp do_add_relationships(specs, resources) do
defp do_add_relationships(specs, resources, opts) do
specs =
Enum.map(specs, fn spec ->
belongs_to_relationships =
Expand Down Expand Up @@ -609,7 +610,7 @@ defmodule AshPostgres.ResourceGenerator.Spec do
[relationship]

{name, relationships} ->
name_all_relationships(:belongs_to, spec, name, relationships)
name_all_relationships(:belongs_to, opts, spec, name, relationships)
end)

%{spec | relationships: belongs_to_relationships}
Expand Down Expand Up @@ -673,17 +674,17 @@ defmodule AshPostgres.ResourceGenerator.Spec do
[relationship]

{name, relationships} ->
name_all_relationships(:has, spec, name, relationships)
name_all_relationships(:has, opts, spec, name, relationships)
end)

%{spec | relationships: spec.relationships ++ relationships_to_me}
end)
end

defp name_all_relationships(type, spec, name, relationships, acc \\ [])
defp name_all_relationships(_type, _spec, _name, [], acc), do: acc
defp name_all_relationships(type, opts, spec, name, relationships, acc \\ [])
defp name_all_relationships(_type, _opts, _spec, _name, [], acc), do: acc

defp name_all_relationships(type, spec, name, [relationship | rest], acc) do
defp name_all_relationships(type, opts, spec, name, [relationship | rest], acc) do
label =
case type do
:belongs_to ->
Expand Down Expand Up @@ -729,10 +730,12 @@ defmodule AshPostgres.ResourceGenerator.Spec do
|> String.trim_leading(":")
|> case do
"" ->
name_all_relationships(type, spec, name, rest, acc)
name_all_relationships(type, opts, spec, name, rest, acc)

new_name ->
name_all_relationships(type, spec, name, rest, [%{relationship | name: new_name} | acc])
name_all_relationships(type, opts, spec, name, rest, [
%{relationship | name: new_name} | acc
])
end
end

Expand Down Expand Up @@ -810,7 +813,7 @@ defmodule AshPostgres.ResourceGenerator.Spec do
end
end

def set_types(attributes) do
def set_types(attributes, opts) do
attributes
|> Enum.map(fn attribute ->
case Process.get({:type_cache, attribute.type}) do
Expand All @@ -820,7 +823,7 @@ defmodule AshPostgres.ResourceGenerator.Spec do
%{attribute | attr_type: type}

:error ->
get_type(attribute)
get_type(attribute, opts)
end

type ->
Expand All @@ -829,19 +832,26 @@ defmodule AshPostgres.ResourceGenerator.Spec do
end)
end

defp get_type(attribute) do
case Mix.shell().prompt("""
Unknown type: #{attribute.type}. What should we use as the type?
defp get_type(attribute, opts) do
result =
if opts[:yes?] do
"skip"
else
Mix.shell().prompt("""
Unknown type: #{attribute.type}. What should we use as the type?
Provide the value as literal source code that should be placed into the
generated file, i.e
Provide the value as literal source code that should be placed into the
generated file, i.e
- :string
- MyApp.Types.CustomType
- {:array, :string}
- :string
- MyApp.Types.CustomType
- {:array, :string}
Use `skip` to skip ignore this attribute.
""")
end

Use `skip` to skip ignore this attribute.
""") do
case result do
skip when skip in ["skip", "skip\n"] ->
attribute

Expand All @@ -861,7 +871,7 @@ defmodule AshPostgres.ResourceGenerator.Spec do
e ->
IO.puts(Exception.format(:error, e, __STACKTRACE__))

get_type(attribute)
get_type(attribute, opts)
end
end
end
Expand Down
27 changes: 27 additions & 0 deletions test/resource_generator_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
defmodule AshPostgres.RelWithParentFilterTest do
use AshPostgres.RepoCase, async: false

setup do
AshPostgres.TestRepo.query!("DROP TABLE IF EXISTS example_table")
AshPostgres.TestRepo.query!("CREATE TABLE example_table (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
name VARCHAR(255),
age INTEGER,
email VARCHAR(255)
)")

on_exit(fn ->
AshPostgres.TestRepo.query!("DROP TABLE IF EXISTS example_table")
end)
end

test "a resource is generated from a table" do
Igniter.new()
|> Igniter.compose_task("ash_postgres.gen.resources", [
"MyApp.Accounts",
"--tables",
"example_table",
"--yes"
])
end
end

0 comments on commit efa4ef0

Please sign in to comment.