Skip to content

Commit

Permalink
Feat: add upsert macro
Browse files Browse the repository at this point in the history
  • Loading branch information
mindreframer committed Dec 13, 2023
1 parent df6d7fb commit bca82b2
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## v0.1.1 (2023-12-13)

- add new macro: `upsert`. It allows providing `:on_conflict` options, defaults to `[on_conflict: :nothing]`

## v0.1.0 (2023-11-29)

- mostly working, need a bit polish
Expand Down
22 changes: 22 additions & 0 deletions lib/dryhard.ex
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,28 @@ defmodule Dryhard do
end
end

defmacro upsert(config, changeset_fn, opts \\ [on_conflict: :nothing]) do
quote bind_quoted: [config: config, changeset_fn: changeset_fn, opts: opts] do
@doc """
Creates a single #{config.plural_name} record (ignores conflicts, like ID / uniq indexes)
Provide upsert options as documented here:
- https://hexdocs.pm/ecto/Ecto.Repo.html#c:insert/2-upserts
Defaults to:
`[on_conflict: :nothing]`
Params:
- attrs: map to pass into the changeset function
"""
def unquote(:"upsert_#{config.singular_name}")(attrs) do
unquote(config.schema)
|> struct()
|> unquote(changeset_fn).(attrs)
|> unquote(config.repo).insert(unquote(opts))
end
end
end

defmacro create(config, changeset_fn) do
quote bind_quoted: [config: config, changeset_fn: changeset_fn] do
@doc """
Expand Down
1 change: 1 addition & 0 deletions priv/repo/migrations/20230320215000_dryhard_migrations.exs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ defmodule Dryhard.Repo.Migrations.CreateTables do

timestamps()
end
create unique_index(:users, [:username])

create table(:posts) do
add :user_id, references(:users)
Expand Down
7 changes: 7 additions & 0 deletions test/dryhard_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ defmodule DryhardTest do
Dryhard.get(@resource)
Dryhard.new(@resource)
Dryhard.create(@resource, &User.changeset/2)
Dryhard.upsert(@resource, &User.changeset/2)
Dryhard.change(@resource, &User.changeset/2)
Dryhard.update(@resource, &User.changeset/2)
Dryhard.delete(@resource)
Expand Down Expand Up @@ -74,6 +75,12 @@ defmodule DryhardTest do
assert user1 == UserContext.get_user_by_username("user1")
end

test "upsert_user works (ignore conflicts on inserts by default)" do
{:ok, user1} = UserContext.upsert_user(%{username: "user1"})
{:ok, _user1_duplicate} = UserContext.upsert_user(%{username: "user1"})
assert user1 == UserContext.get_user_by_username("user1")
end

test "update_user works" do
{:ok, user1} = UserContext.create_user(%{username: "user1"})
assert user1 == UserContext.get_user_by_username("user1")
Expand Down

0 comments on commit bca82b2

Please sign in to comment.