From a9913a699999e7f98a5472c33921f223a8743831 Mon Sep 17 00:00:00 2001 From: Zach Daniel Date: Thu, 5 Sep 2024 12:54:13 -0400 Subject: [PATCH] improvement: better imported index names improvement: add `--extend` option, forwarded to generated resource --- lib/mix/tasks/ash_postgres.gen.resources.ex | 3 + lib/resource_generator/resource_generator.ex | 66 ++++++++++---------- lib/resource_generator/spec.ex | 23 ++++++- 3 files changed, 57 insertions(+), 35 deletions(-) diff --git a/lib/mix/tasks/ash_postgres.gen.resources.ex b/lib/mix/tasks/ash_postgres.gen.resources.ex index 346bbda..5e270f8 100644 --- a/lib/mix/tasks/ash_postgres.gen.resources.ex +++ b/lib/mix/tasks/ash_postgres.gen.resources.ex @@ -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. + - `extend`, `e` - Extension or extensions to apply to the generated resources. See `mix ash.patch.extend` for more. - `yes`, `y` - Answer yes (or skip) to all questions. ## Tables @@ -45,6 +46,7 @@ defmodule Mix.Tasks.AshPostgres.Gen.Resources do yes: :boolean, tables: :keep, skip_tables: :keep, + extend: :keep, snapshots_only: :boolean, domain: :keep ], @@ -52,6 +54,7 @@ defmodule Mix.Tasks.AshPostgres.Gen.Resources do t: :tables, y: :boolean, r: :repo, + e: :extend, d: :domain, s: :skip_tables ] diff --git a/lib/resource_generator/resource_generator.ex b/lib/resource_generator/resource_generator.ex index 81ef6af..d29b580 100644 --- a/lib/resource_generator/resource_generator.ex +++ b/lib/resource_generator/resource_generator.ex @@ -13,33 +13,7 @@ defmodule AshPostgres.ResourceGenerator do igniter = Igniter.include_all_elixir_files(igniter) - opts = - if opts[:tables] do - Keyword.put( - opts, - :tables, - opts[:tables] - |> List.wrap() - |> Enum.join(",") - |> String.split(",") - ) - else - opts - end - - opts = - if opts[:skip_tables] do - Keyword.put( - opts, - :skip_tables, - opts[:skip_tables] - |> List.wrap() - |> Enum.join(",") - |> String.split(",") - ) - else - opts - end + opts = handle_csv_opts(opts, [:tables, :skip_tables, :extend]) specs = repos @@ -75,6 +49,23 @@ defmodule AshPostgres.ResourceGenerator do end) end + defp handle_csv_opts(opts, keys) do + Enum.reduce(keys, opts, fn key, opts -> + opts + |> Keyword.get_values(key) + |> case do + [] -> + opts + + values -> + values + |> Enum.join(",") + |> String.split(",", trim: true) + |> then(&Keyword.put(opts, key, &1)) + end + end) + end + defp table_to_resource( igniter, %AshPostgres.ResourceGenerator.Spec{} = table_spec, @@ -113,6 +104,15 @@ defmodule AshPostgres.ResourceGenerator do igniter |> Ash.Domain.Igniter.add_resource_reference(domain, table_spec.resource) |> Igniter.Code.Module.create_module(table_spec.resource, resource) + |> then(fn igniter -> + if opts[:extend] do + Igniter.compose_task(igniter, "ash.patch.extend", [ + table_spec.resource | opts[:extend] || [] + ]) + else + igniter + end + end) end defp check_constraints(%{check_constraints: _check_constraints}, true) do @@ -138,7 +138,7 @@ defmodule AshPostgres.ResourceGenerator do """ end - defp skip_unique_indexes(%{indexes: indexes}) do + defp skip_unique_indexes(%{table_name: table_name, indexes: indexes}) do indexes |> Enum.filter(fn %{unique?: unique?, columns: columns} -> unique? && Enum.all?(columns, &Regex.match?(~r/^[0-9a-zA-Z_]+$/, &1)) @@ -150,12 +150,12 @@ defmodule AshPostgres.ResourceGenerator do indexes -> """ - skip_unique_indexes [#{Enum.map_join(indexes, ",", &":#{&1.name}")}] + skip_unique_indexes [#{Enum.map_join(indexes, ",", &":#{&1.identity_name}")}] """ end end - defp identity_index_names(%{indexes: indexes}) do + defp identity_index_names(%{table_name: table_name, indexes: indexes}) do indexes |> Enum.filter(fn %{unique?: unique?, columns: columns} -> unique? && Enum.all?(columns, &Regex.match?(~r/^[0-9a-zA-Z_]+$/, &1)) @@ -167,19 +167,19 @@ defmodule AshPostgres.ResourceGenerator do indexes -> indexes |> Enum.map_join(", ", fn index -> - "#{index.name}: \"#{index.name}\"" + "#{index.identity_name}: \"#{index.name}\"" end) |> then(&"identity_index_names [#{&1}]") end end - defp add_identities(str, %{indexes: indexes}) do + defp add_identities(str, %{table_name: table_name, indexes: indexes}) do indexes |> Enum.filter(fn %{unique?: unique?, columns: columns} -> unique? && Enum.all?(columns, &Regex.match?(~r/^[0-9a-zA-Z_]+$/, &1)) end) |> Enum.map(fn index -> - name = index.name + name = index.identity_name fields = "[" <> Enum.map_join(index.columns, ", ", &":#{&1}") <> "]" diff --git a/lib/resource_generator/spec.ex b/lib/resource_generator/spec.ex index fe9fa24..607e2ae 100644 --- a/lib/resource_generator/spec.ex +++ b/lib/resource_generator/spec.ex @@ -48,7 +48,16 @@ defmodule AshPostgres.ResourceGenerator.Spec do defmodule Index do @moduledoc false - defstruct [:name, :columns, :unique?, :nulls_distinct, :where_clause, :using, :include] + defstruct [ + :name, + :columns, + :unique?, + :nulls_distinct, + :where_clause, + :using, + :include, + :identity_name + ] end defmodule CheckConstraint do @@ -196,7 +205,8 @@ defmodule AshPostgres.ResourceGenerator.Spec do contype = 'c' AND conrelid::regclass::text = $1 """, - [spec.table_name] + [spec.table_name], + log: false ) attribute = Enum.find(spec.attributes, & &1.primary_key?) || Enum.at(spec.attributes, 0) @@ -290,9 +300,18 @@ defmodule AshPostgres.ResourceGenerator.Spec do nil end + identity_name = + index_name + |> String.trim_leading(spec.table_name <> "_") + |> String.trim_leading("unique_") + |> String.replace("_unique_", "_") + |> String.trim_trailing("_index") + |> String.replace("_index_", "_") + [ %Index{ name: index_name, + identity_name: identity_name, columns: Enum.uniq(columns), unique?: is_unique, include: include,