Custom functions in MyProject.Repo

565 views
Skip to first unread message

Steve Pallen

unread,
Jul 21, 2016, 11:26:01 AM7/21/16
to elixir-ecto
I'm trying to get custom functions working in my Repo. 

I have done the following:

```elixir
defmodule Admin.Repo do
  use Ecto.Repo, otp_app: :admin
  use Scrivener, page_size: 10

  defoverridable [update!: 2, update: 2, delete!: 2, delete: 2]

  def update(struct, opts \\ []) do
    #  ...
  end
  # ...
```

This is working. My update and delete functions work, but I'm getting compiler warnings

`warning: this clause cannot match because a previous clause at line 2 always matches`

What am I doing wrong?

Steve

Paul Clegg

unread,
Jul 21, 2016, 11:42:12 AM7/21/16
to elixi...@googlegroups.com
I think Ecto.Repo already defines update, so when you redefine it, you get the warning.  If you don't want to use the original update, add "except: [update: 2]" to the use Ecto.Repo line (I think that works for use -- I know it works for import...)

...Paul



--
You received this message because you are subscribed to the Google Groups "elixir-ecto" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-ecto...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-ecto/1ccd3ae2-38a9-48b8-b114-807496ad7daa%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

José Valim

unread,
Jul 21, 2016, 11:48:02 AM7/21/16
to elixi...@googlegroups.com
It is due to the optional arguments. Just remove them because Ecto has already defined those.

I also need to go on record and say that overriding functions that were not meant to be overridable is a really bad practice and I would avoid doing so. If you need to do paper trail, I would do changeset based operations or a way you can compose.

For more options, visit https://groups.google.com/d/optout.


--


José Valim
Skype: jv.ptec
Founder and Director of R&D

Steve Pallen

unread,
Jul 21, 2016, 12:09:18 PM7/21/16
to elixi...@googlegroups.com
Thanks José.

Yes, I’m doing paper trail (not sure how you knew I was doing that LOL). Are you suggesting that I build 1 changeset that does the update and inserts a Version record? If so, can I do that without altering the original schema for the versioned model? Or are you suggesting that I add the Version insert in the controller’s update action.

Furthermore, I want to hook into the delete action to insert a Version record on delete. Normally, delete is called with the schema(model) and not a changeset.

Here is my Version schema:

```elixir
defmodule Whatwasit.Version do
use Ecto.Schema
import Ecto
import Ecto.Changeset

schema "versions" do
field :item_type, :string
field :item_id, :integer
field :action, :string # ~w(update delete)
field :object, :map # versioned schema stored as a map
field :whodoneit_name, :string # store name also to track if user is later deleted
belongs_to :whodoneit, Admin.User # TODO: need to get Admin.User from config
timestamps
end

def changeset(model, params \\ %{}) do
params = update_in params, [:object], &(Map.delete(&1, :__meta__) |> Map.delete(:__struct__))
model
|> cast(params, ~w(item_type item_id object whodoneit_id action whodoneit_name))
|> validate_required(~w(item_type item_id object)a)
end
end
```

Steve


José Valim

unread,
Jul 21, 2016, 12:37:13 PM7/21/16
to elixi...@googlegroups.com
There is a function called prepare_changes or something similar in changesets that you could use to annotate any action. Although it should be also used sparingly, for this case it seems like the perfect solution.
--
You received this message because you are subscribed to the Google Groups "elixir-ecto" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-ecto...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-ecto/BDA447CF-2AB0-4459-A6A6-82E462B9CC48%40gmail.com.

For more options, visit https://groups.google.com/d/optout.

Steve Pallen

unread,
Jul 21, 2016, 12:50:31 PM7/21/16
to elixi...@googlegroups.com
Yes, looks like just what I need. May also be able to use that from something I’m trying to solve with ExAdmin :)

Thanks José

Steve Pallen

unread,
Jul 21, 2016, 11:45:29 PM7/21/16
to elixi...@googlegroups.com
Here is what I ended up with. 

Steve Pallen

unread,
Jul 31, 2016, 10:37:09 AM7/31/16
to elixir-ecto
José, so prepare_changes works well for update and delete actions. However, I would like to now hook into the insert action to create and link a new version record. But it looks like prepare_changes does not have access to the newly inserted schema (which is consistent with the docs saying its run before the database operation). Any suggestions how I hook into the repo operation after the insert so I can get access to it id?

José Valim

unread,
Jul 31, 2016, 10:42:28 AM7/31/16
to elixi...@googlegroups.com
Unfortunately I don't have any. You would have to use Ecto.Multi but I am not sure if you want to convert to a Multi at this point.
--
You received this message because you are subscribed to the Google Groups "elixir-ecto" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-ecto...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-ecto/a6f1bae4-6c41-4455-a130-1d39bf878e81%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Steve Pallen

unread,
Jul 31, 2016, 10:48:25 AM7/31/16
to elixi...@googlegroups.com
Thanks for the quick response José!!

So I guess I have two options:

1. Override insert functions in the repo which you already discouraged :)
2. Add an API to be used on the create action of the controller, to do the insert and Version insert. 

I’ll go with #2.

You received this message because you are subscribed to a topic in the Google Groups "elixir-ecto" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elixir-ecto/4LqqqFtdILU/unsubscribe.
To unsubscribe from this group and all its topics, send an email to elixir-ecto...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-ecto/CAGnRm4LzpGxGD%3DPgrLUKhEvXkmHUv7QtcFndxwjoWt%2BgGbZRgg%40mail.gmail.com.

Michał Muskała

unread,
Jul 31, 2016, 10:53:05 AM7/31/16
to elixi...@googlegroups.com

On 31 Jul 2016, at 16:48, Steve Pallen <smpal...@gmail.com> wrote:

Thanks for the quick response José!!

So I guess I have two options:

1. Override insert functions in the repo which you already discouraged :)
2. Add an API to be used on the create action of the controller, to do the insert and Version insert. 

I’ll go with #2.

While overriding insert is probably not a good idea, providing something like insert_versioned that has the same interface as insert and manages the version would probably be quite a good API.

Michał.
signature.asc

Steve Pallen

unread,
Jul 31, 2016, 10:55:35 AM7/31/16
to elixi...@googlegroups.com
Good idea. Thanks!!

Reply all
Reply to author
Forward
0 new messages