From 26668df73d1fde5e99fda2da5cde76b0563c3142 Mon Sep 17 00:00:00 2001 From: Zach Daniel Date: Mon, 21 Nov 2022 02:38:00 -0500 Subject: [PATCH] improvement: add `migration_defaults` for customizing default values --- lib/data_layer.ex | 9 +++++ lib/data_layer/info.ex | 7 +++- .../migration_generator.ex | 37 ++++++++++++------- 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/lib/data_layer.ex b/lib/data_layer.ex index 934ee1c..ea253f2 100644 --- a/lib/data_layer.ex +++ b/lib/data_layer.ex @@ -293,6 +293,15 @@ defmodule AshPostgres.DataLayer do doc: "A keyword list of attribute names to the ecto migration type that should be used for that attribute. Only necessary if you need to override the defaults." ], + migration_defaults: [ + type: :keyword_list, + default: [], + doc: """ + A keyword list of attribute names to the ecto migration default that should be used for that attribute. Only necessary if you need to override the defaults. + + The string you use will be placed verbatim in the migration. Use fragments like `fragment(\\\\"now()\\\\")`, or for `nil`, use `\\\\"nil\\\\"`. + """ + ], base_filter_sql: [ type: :string, doc: diff --git a/lib/data_layer/info.ex b/lib/data_layer/info.ex index a4746f8..ae33e72 100644 --- a/lib/data_layer/info.ex +++ b/lib/data_layer/info.ex @@ -25,7 +25,12 @@ defmodule AshPostgres.DataLayer.Info do @doc "A keyword list of customized migration types" def migration_types(resource) do - Extension.get_opt(resource, [:postgres], :migration_types, nil, true) + Extension.get_opt(resource, [:postgres], :migration_types, []) + end + + @doc "A keyword list of customized migration defaults" + def migration_defaults(resource) do + Extension.get_opt(resource, [:postgres], :migration_defaults, []) end @doc "The configured check_constraints for a resource" diff --git a/lib/migration_generator/migration_generator.ex b/lib/migration_generator/migration_generator.ex index 19dd2fc..ff55b8a 100644 --- a/lib/migration_generator/migration_generator.ex +++ b/lib/migration_generator/migration_generator.ex @@ -1909,6 +1909,7 @@ defmodule AshPostgres.MigrationGenerator do destination_attribute_default: default( source_attribute, + relationship.destination, AshPostgres.DataLayer.Info.repo(relationship.destination) ), destination_attribute_generated: source_attribute.generated?, @@ -2040,7 +2041,7 @@ defmodule AshPostgres.MigrationGenerator do &Map.take(&1, [:name, :source, :type, :default, :allow_nil?, :generated?, :primary_key?]) ) |> Enum.map(fn attribute -> - default = default(attribute, repo) + default = default(attribute, resource, repo) type = AshPostgres.DataLayer.Info.migration_types(resource)[attribute.name] || @@ -2210,22 +2211,32 @@ defmodule AshPostgres.MigrationGenerator do @uuid_functions [&Ash.UUID.generate/0, &Ecto.UUID.generate/0] - defp default(%{default: default}, _repo) when is_function(default) do - cond do - default in @uuid_functions -> - ~S[fragment("gen_random_uuid()")] + defp default(%{name: name, default: default}, resource, _repo) when is_function(default) do + configured_default(resource, name) || + cond do + default in @uuid_functions -> + ~S[fragment("gen_random_uuid()")] - default == (&DateTime.utc_now/0) -> - ~S[fragment("now()")] + default == (&DateTime.utc_now/0) -> + ~S[fragment("now()")] - true -> - "nil" - end + true -> + "nil" + end end - defp default(%{default: {_, _, _}}, _), do: "nil" - defp default(%{default: nil}, _), do: "nil" - defp default(%{default: value}, _), do: EctoMigrationDefault.to_default(value) + defp default(%{name: name, default: {_, _, _}}, resource, _), + do: configured_default(resource, name) || "nil" + + defp default(%{name: name, default: nil}, resource, _), + do: configured_default(resource, name) || "nil" + + defp default(%{name: name, default: value}, resource, _), + do: configured_default(resource, name) || EctoMigrationDefault.to_default(value) + + defp configured_default(resource, attribute) do + AshPostgres.DataLayer.Info.migration_defaults(resource)[attribute] + end defp snapshot_to_binary(snapshot) do snapshot