I really liked this idea and I have applied to application I’m working on.
Migrations are already working for me really well. MyApp.Repo.delete/2 also works (it do what it should), but at end it raises extra error (after soft delete was triggered):
[debug] QUERY OK db=6.0ms queue=1.6ms
DELETE FROM "my_schema_view" WHERE "id" = $1 [1]
** (Ecto.StaleEntryError) attempted to delete a stale struct:
%MyApp.MyContext.MySchema{__meta__: #Ecto.Schema.Metadata<:loaded, "my_schema_view">, …}
(ecto) lib/ecto/repo/schema.ex:667: Ecto.Repo.Schema.apply/4
(ecto) lib/ecto/repo/schema.ex:442: anonymous fn/10 in Ecto.Repo.Schema.do_delete/3
As said the weird behaviour is that it raises after everything goes well. Also following documentation it should not raise - instead it should return {:error, Ecto.Changeset.t()}.
I know why it’s called stale, but as said it’s expected and also it works really well (I hit trigger without problem) and I have just this one not needed error in console. The question is how to fix it?
I’m not sure if my special case is good to fill a bug, but on the other side it raises when it should not … What do you think about it?
I missed that, because I was looking at spec only and saw that it always returns {:ok, result} or {:error, changeset} and did not even though that it could be changed in such way. I think that in docs there should be no_return also, right? Anyway it’s working as expected now, thanks!
I’m trying to use the stale_error_field option without success: the Ecto.StaleEntryError still rises.
I don’t correctly understand what should be set as a field and what should it do.
defmodule MyApp.Repo do
use Ecto.Repo, otp_app: :my_app
defoverridable update: 2, update!: 2
def update(struct, opts) do
super(struct, Keyword.merge(opts, [stale_error_field: :id]))
end
def update!(struct, opts) do
super(struct, Keyword.merge(opts, [stale_error_field: :id]))
end
@augnustin Yeah, it was something about year ago, so I do not remember correctly … However if you are looking for examples then even before forum/google you should check test folder
Feel free to experiment over there and apply updated code to your project.
Here are lines of tests for stale_error_field option:
Of course put_in(my_schema.__meta__.context… is only for tests (normally it’s set somewhere in ecto code) and you should not work on __meta__ key.
Here you can check a pattern match where ecto_sql thinks that the return gives stale:
If I hardcode this:
def query(conn, sql, params, options) do
query = %Exqlite.Query{statement: IO.iodata_to_binary(sql)}
case DBConnection.prepare_execute(conn, query, params, options) do
{:ok, _, result} ->
if sql |> List.first() |> String.starts_with?("DELETE") do
{:ok, %{result | num_rows: 1, rows: nil}}
else
{:ok, result}
end
other ->
other
end
end