diff --git a/lib/decentralised_book_index/metadata.ex b/lib/decentralised_book_index/metadata.ex index fc6e0b1..1dbf447 100644 --- a/lib/decentralised_book_index/metadata.ex +++ b/lib/decentralised_book_index/metadata.ex @@ -88,5 +88,13 @@ defmodule DecentralisedBookIndex.Metadata do define :update_book_id, action: :update define :destroy_book_id, action: :destroy end + + resource DecentralisedBookIndex.Metadata.Publisher do + define :create_publisher, action: :create, args: [:name] + define :list_publishers, action: :read + define :get_publisher_by_id, args: [:id], action: :by_id + define :update_publisher, action: :update + define :destroy_publisher, action: :destroy + end end end diff --git a/lib/decentralised_book_index/metadata/book.ex b/lib/decentralised_book_index/metadata/book.ex index 4df1d6a..d025fa9 100644 --- a/lib/decentralised_book_index/metadata/book.ex +++ b/lib/decentralised_book_index/metadata/book.ex @@ -17,7 +17,7 @@ defmodule DecentralisedBookIndex.Metadata.Book do create :create do primary? true - accept [:title, :description, :book_editions_registry_id] + accept [:title, :description, :publisher_id, :book_editions_registry_id] argument :bids, {:array, :map} argument :author_roles, {:array, :map} @@ -38,7 +38,7 @@ defmodule DecentralisedBookIndex.Metadata.Book do end create :add_book_to_related_editions_registry do - accept [:title, :description] + accept [:title, :description, :publisher_id] argument :related_book_id, :uuid do allow_nil? false @@ -121,6 +121,8 @@ defmodule DecentralisedBookIndex.Metadata.Book do relationships do belongs_to :book_editions_registry, Metadata.BookEditionsRegistry + belongs_to :publisher, Metadata.Publisher + has_many :author_roles, Metadata.AuthorRole do sort order: :asc public? true diff --git a/lib/decentralised_book_index/metadata/publisher.ex b/lib/decentralised_book_index/metadata/publisher.ex new file mode 100644 index 0000000..0c2a61d --- /dev/null +++ b/lib/decentralised_book_index/metadata/publisher.ex @@ -0,0 +1,44 @@ +defmodule DecentralisedBookIndex.Metadata.Publisher do + use Ash.Resource, + otp_app: :decentralised_book_index, + domain: DecentralisedBookIndex.Metadata, + data_layer: AshPostgres.DataLayer + + require Ash.Query + alias DecentralisedBookIndex.Metadata + + postgres do + table "publishers" + repo DecentralisedBookIndex.Repo + end + + actions do + defaults [:read, :update, :destroy] + + create :create do + primary? true + accept [:name] + end + + read :by_id do + argument :id, :uuid, allow_nil?: false + get? true + filter expr(id == ^arg(:id)) + end + end + + attributes do + uuid_primary_key :id + + attribute :name, :string do + allow_nil? false + public? true + end + + timestamps() + end + + relationships do + has_many :books, Metadata.Book + end +end diff --git a/priv/repo/migrations/20250315185359_add_publisher_and_update_book_relationship.exs b/priv/repo/migrations/20250315185359_add_publisher_and_update_book_relationship.exs new file mode 100644 index 0000000..a8a0556 --- /dev/null +++ b/priv/repo/migrations/20250315185359_add_publisher_and_update_book_relationship.exs @@ -0,0 +1,44 @@ +defmodule DecentralisedBookIndex.Repo.Migrations.AddPublisherAndUpdateBookRelationship do + @moduledoc """ + Updates resources based on their most recent snapshots. + + This file was autogenerated with `mix ash_postgres.generate_migrations` + """ + + use Ecto.Migration + + def up do + create table(:publishers, primary_key: false) do + add :id, :uuid, null: false, default: fragment("gen_random_uuid()"), primary_key: true + add :name, :text, null: false + + add :inserted_at, :utc_datetime_usec, + null: false, + default: fragment("(now() AT TIME ZONE 'utc')") + + add :updated_at, :utc_datetime_usec, + null: false, + default: fragment("(now() AT TIME ZONE 'utc')") + end + + alter table(:books) do + add :publisher_id, + references(:publishers, + column: :id, + name: "books_publisher_id_fkey", + type: :uuid, + prefix: "public" + ) + end + end + + def down do + drop constraint(:books, "books_publisher_id_fkey") + + alter table(:books) do + remove :publisher_id + end + + drop table(:publishers) + end +end diff --git a/priv/resource_snapshots/repo/books/20250315185359.json b/priv/resource_snapshots/repo/books/20250315185359.json new file mode 100644 index 0000000..22d4f2e --- /dev/null +++ b/priv/resource_snapshots/repo/books/20250315185359.json @@ -0,0 +1,127 @@ +{ + "attributes": [ + { + "allow_nil?": false, + "default": "fragment(\"gen_random_uuid()\")", + "generated?": false, + "primary_key?": true, + "references": null, + "size": null, + "source": "id", + "type": "uuid" + }, + { + "allow_nil?": false, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "title", + "type": "text" + }, + { + "allow_nil?": false, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "description", + "type": "text" + }, + { + "allow_nil?": false, + "default": "fragment(\"(now() AT TIME ZONE 'utc')\")", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "inserted_at", + "type": "utc_datetime_usec" + }, + { + "allow_nil?": false, + "default": "fragment(\"(now() AT TIME ZONE 'utc')\")", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "updated_at", + "type": "utc_datetime_usec" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": { + "deferrable": false, + "destination_attribute": "id", + "destination_attribute_default": null, + "destination_attribute_generated": null, + "index?": false, + "match_type": null, + "match_with": null, + "multitenancy": { + "attribute": null, + "global": null, + "strategy": null + }, + "name": "books_book_editions_registry_id_fkey", + "on_delete": null, + "on_update": null, + "primary_key?": true, + "schema": "public", + "table": "book_editions_registries" + }, + "size": null, + "source": "book_editions_registry_id", + "type": "uuid" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": { + "deferrable": false, + "destination_attribute": "id", + "destination_attribute_default": null, + "destination_attribute_generated": null, + "index?": false, + "match_type": null, + "match_with": null, + "multitenancy": { + "attribute": null, + "global": null, + "strategy": null + }, + "name": "books_publisher_id_fkey", + "on_delete": null, + "on_update": null, + "primary_key?": true, + "schema": "public", + "table": "publishers" + }, + "size": null, + "source": "publisher_id", + "type": "uuid" + } + ], + "base_filter": null, + "check_constraints": [], + "custom_indexes": [], + "custom_statements": [], + "has_create_action": true, + "hash": "300A3E949AD533F77BA317D27879A00127B75EF995918F065811DB96ED1BC6F8", + "identities": [], + "multitenancy": { + "attribute": null, + "global": null, + "strategy": null + }, + "repo": "Elixir.DecentralisedBookIndex.Repo", + "schema": null, + "table": "books" +} \ No newline at end of file diff --git a/priv/resource_snapshots/repo/publishers/20250315185359.json b/priv/resource_snapshots/repo/publishers/20250315185359.json new file mode 100644 index 0000000..6ce81a0 --- /dev/null +++ b/priv/resource_snapshots/repo/publishers/20250315185359.json @@ -0,0 +1,59 @@ +{ + "attributes": [ + { + "allow_nil?": false, + "default": "fragment(\"gen_random_uuid()\")", + "generated?": false, + "primary_key?": true, + "references": null, + "size": null, + "source": "id", + "type": "uuid" + }, + { + "allow_nil?": false, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "name", + "type": "text" + }, + { + "allow_nil?": false, + "default": "fragment(\"(now() AT TIME ZONE 'utc')\")", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "inserted_at", + "type": "utc_datetime_usec" + }, + { + "allow_nil?": false, + "default": "fragment(\"(now() AT TIME ZONE 'utc')\")", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "updated_at", + "type": "utc_datetime_usec" + } + ], + "base_filter": null, + "check_constraints": [], + "custom_indexes": [], + "custom_statements": [], + "has_create_action": true, + "hash": "B93F1B7B70B8C5407B5E7CACF23275E9B054BCF49D147940480E54C08C69CB21", + "identities": [], + "multitenancy": { + "attribute": null, + "global": null, + "strategy": null + }, + "repo": "Elixir.DecentralisedBookIndex.Repo", + "schema": null, + "table": "publishers" +} \ No newline at end of file