diff --git a/README.md b/README.md index 00caa09..a457faa 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ AshCubDb is still a work in progress. Feel free to give it a go. | Read (sort) | ✅ | | Read (calculations) | ❌ | | Read (aggregates) | ❌ | -| Update | ❌ | +| Update | ✅ | | Destroy | ❌ | ## Github Mirror diff --git a/config/config.exs b/config/config.exs index cf76d0a..5a5bc1b 100644 --- a/config/config.exs +++ b/config/config.exs @@ -10,4 +10,6 @@ config :git_ops, if Mix.env() in ~w[dev test]a do config :ash_cubdb, ash_apis: [Support.Api] + + config :spark, :formatter, remove_parens?: true end diff --git a/lib/ash_cub_db/data_layer.ex b/lib/ash_cub_db/data_layer.ex index 53b1df8..54be159 100644 --- a/lib/ash_cub_db/data_layer.ex +++ b/lib/ash_cub_db/data_layer.ex @@ -14,6 +14,7 @@ defmodule AshCubDB.DataLayer do Changeset, Error, Error.Changes.InvalidAttribute, + Error.Changes.StaleRecord, Error.Invalid.TenantRequired, Filter.Runtime, Resource @@ -50,6 +51,7 @@ defmodule AshCubDB.DataLayer do @doc false @impl true def can?(resource, :create), do: Dir.writable?(resource) + def can?(resource, :update), do: Dir.writable?(resource) def can?(resource, :upsert), do: Dir.writable?(resource) def can?(resource, :read), do: Dir.readable?(resource) def can?(_, :multitenancy), do: true @@ -107,6 +109,22 @@ defmodule AshCubDB.DataLayer do end end + @doc false + @impl true + def update(resource, changeset) do + with :ok <- validate_tenant_configuration(resource, changeset.tenant), + {:ok, db} <- start(resource), + {:ok, record} <- Changeset.apply_attributes(changeset), + {:ok, key, data} <- Serde.serialise(record), + true <- CubDB.has_key?(db, key), + :ok <- CubDB.put(db, key, data) do + {:ok, set_loaded(record)} + else + false -> {:error, StaleRecord.exception(resource: resource)} + {:error, reason} -> {:error, Ash.Error.to_ash_error(reason)} + end + end + @doc false @impl true def run_query(query, resource, parent \\ nil) do diff --git a/test/ash_cub_db/data_layer_test.exs b/test/ash_cub_db/data_layer_test.exs index d5837d2..5040a94 100644 --- a/test/ash_cub_db/data_layer_test.exs +++ b/test/ash_cub_db/data_layer_test.exs @@ -129,6 +129,21 @@ defmodule AshCubDB.DataLayerTest do end end + describe "update" do + test "records can be updated" do + post = insert!(Post) + params = Post |> params!() |> Map.take([:title]) + + assert {:ok, updated} = Post.update(post, params) + assert updated.id == post.id + assert updated.title == params.title + + assert {:ok, updated} = Post.get(post.id) + assert updated.id == post.id + assert updated.title == params.title + end + end + defp dump(resource) do resource |> via() diff --git a/test/support/post.ex b/test/support/post.ex index 7f65af5..ffac374 100644 --- a/test/support/post.ex +++ b/test/support/post.ex @@ -7,27 +7,29 @@ defmodule Support.Post do end attributes do - uuid_primary_key(:id) do - writable?(true) + uuid_primary_key :id do + writable? true end - attribute(:title, :string) - attribute(:body, :string) + attribute :title, :string + attribute :body, :string end actions do # defaults ~w[create read update destroy]a - defaults(~w[create read]a) + defaults ~w[create read update]a end relationships do - belongs_to(:author, Support.Author) + belongs_to :author, Support.Author end code_interface do - define_for(Support.Api) + define_for Support.Api - define(:create) - define(:read) + define :create + define :read + define :update + define :get, action: :read, get_by: [:id] end end