Skip to content

Commit

Permalink
fix: Allow empty extra_columns/trigger_columns options
Browse files Browse the repository at this point in the history
  • Loading branch information
cheerfulstoic committed Aug 12, 2024
1 parent 9aa43c9 commit eff9e32
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 32 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

**IMPORTANT NOTE**: Make sure to see the [Upgrading Versions](guides/howtos/Upgrading Versions.md) guide in the [HexDocs documentation](https://hexdocs.pm/ecto_watch) if you're having an issue after upgrading.

## [0.9.11] - 2023-08-12

### Fixed

- Allow empty `trigger_columns` and `extra_columns` options (#24 / thanks @barrelltech)

## [0.9.10] - 2023-08-12

### Fixed
Expand Down
13 changes: 8 additions & 5 deletions lib/ecto_watch/options/watcher_options.ex
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,13 @@ defmodule EctoWatch.Options.WatcherOptions do
type:
{:custom, __MODULE__, :validate_trigger_columns,
[opts[:label], schema_definition, update_type]},
required: false
required: false,
default: []
],
extra_columns: [
type: {:custom, __MODULE__, :validate_columns, [schema_definition]},
required: false
required: false,
default: []
]
]

Expand All @@ -163,6 +165,10 @@ defmodule EctoWatch.Options.WatcherOptions do
end
end

def validate_trigger_columns([], _, _, _) do
{:ok, []}
end

def validate_trigger_columns(columns, label, schema_definition, update_type) do
cond do
update_type != :updated ->
Expand All @@ -177,9 +183,6 @@ defmodule EctoWatch.Options.WatcherOptions do
end
end

def validate_columns([], _schema_mod),
do: {:error, "List must not be empty"}

def validate_columns(columns, schema_definition) do
Helpers.validate_list(columns, fn
column when is_atom(column) ->
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ defmodule EctoWatch.MixProject do
def project do
[
app: :ecto_watch,
version: "0.9.10",
version: "0.9.11",
elixir: "~> 1.10",
description:
"EctoWatch allows you to easily get Phoenix.PubSub notifications directly from postgresql.",
Expand Down
113 changes: 87 additions & 26 deletions test/ecto_watch_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -384,32 +384,6 @@ defmodule EctoWatchTest do
end
end

test "columns must be non-empty" do
assert_raise ArgumentError,
~r/invalid value for :watchers option: invalid value for :trigger_columns option: List must not be empty/,
fn ->
EctoWatch.start_link(
repo: TestRepo,
pub_sub: TestPubSub,
watchers: [
{Thing, :updated, label: :thing_custom_event, trigger_columns: []}
]
)
end

assert_raise ArgumentError,
~r/invalid value for :watchers option: invalid value for :extra_columns option: List must not be empty/,
fn ->
EctoWatch.start_link(
repo: TestRepo,
pub_sub: TestPubSub,
watchers: [
{Thing, :updated, label: :thing_custom_event, extra_columns: []}
]
)
end
end

test "columns must be in schema" do
assert_raise ArgumentError,
~r/invalid value for :watchers option: invalid value for :trigger_columns option: Invalid column: :not_a_column \(expected to be in \[:id, :the_string, :the_integer, :the_float, :parent_thing_id, :other_parent_thing_id, :inserted_at, :updated_at\]\)/,
Expand Down Expand Up @@ -761,6 +735,42 @@ defmodule EctoWatchTest do
assert_receive {:other_inserted, %{weird_id: 1234}}
end

test "empty extra_columns list" do
start_supervised!({EctoWatch,
repo: TestRepo,
pub_sub: TestPubSub,
watchers: [
{Thing, :inserted, extra_columns: []},
{Other, :inserted, extra_columns: []},
# schemaless definition
{%{table_name: :things}, :inserted, label: :things_inserted, extra_columns: []},
{%{table_name: :other, schema_prefix: "0xabcd", primary_key: :weird_id}, :inserted,
label: :other_inserted, extra_columns: []}
]})

EctoWatch.subscribe({Thing, :inserted})
EctoWatch.subscribe({Other, :inserted})
EctoWatch.subscribe(:things_inserted)
EctoWatch.subscribe(:other_inserted)

Ecto.Adapters.SQL.query!(
TestRepo,
"INSERT INTO things (the_string, the_integer, the_float, inserted_at, updated_at) VALUES ('the value', 4455, 84.52, NOW(), NOW())",
[]
)

Ecto.Adapters.SQL.query!(
TestRepo,
"INSERT INTO \"0xabcd\".other (weird_id, the_string, inserted_at, updated_at) VALUES (1234, 'the value', NOW(), NOW())",
[]
)

assert_receive {{Thing, :inserted}, %{id: 3}}
assert_receive {:things_inserted, %{id: 3}}
assert_receive {{Other, :inserted}, %{weird_id: 1234}}
assert_receive {:other_inserted, %{weird_id: 1234}}
end

test "inserts for an association column", %{already_existing_id2: already_existing_id2} do
start_supervised!(
{EctoWatch,
Expand Down Expand Up @@ -886,6 +896,32 @@ defmodule EctoWatchTest do
assert_receive {:things_updated, %{id: ^already_existing_id2}}
end

test "empty column lists", %{
already_existing_id1: already_existing_id1,
already_existing_id2: already_existing_id2
} do
start_supervised!({EctoWatch,
repo: TestRepo,
pub_sub: TestPubSub,
watchers: [
{Thing, :updated, trigger_columns: [], extra_columns: []},
# schemaless definition
{%{table_name: :things}, :updated,
label: :things_updated, trigger_columns: [], extra_columns: []}
]})

EctoWatch.subscribe({Thing, :updated})
EctoWatch.subscribe(:things_updated)

Ecto.Adapters.SQL.query!(TestRepo, "UPDATE things SET the_string = 'the new value'", [])

assert_receive {{Thing, :updated}, %{id: ^already_existing_id1}}
assert_receive {:things_updated, %{id: ^already_existing_id1}}

assert_receive {{Thing, :updated}, %{id: ^already_existing_id2}}
assert_receive {:things_updated, %{id: ^already_existing_id2}}
end

test "updates for the primary key", %{
already_existing_id1: already_existing_id1,
already_existing_id2: already_existing_id2
Expand Down Expand Up @@ -1097,6 +1133,31 @@ defmodule EctoWatchTest do
assert_receive {:things_deleted, %{id: ^already_existing_id2}}
end

test "empty extra_columns", %{
already_existing_id1: already_existing_id1,
already_existing_id2: already_existing_id2
} do
start_supervised!({EctoWatch,
repo: TestRepo,
pub_sub: TestPubSub,
watchers: [
{Thing, :deleted, extra_columns: []},
# schemaless definition
{%{table_name: :things}, :deleted, label: :things_deleted, extra_columns: []}
]})

EctoWatch.subscribe({Thing, :deleted})
EctoWatch.subscribe(:things_deleted)

Ecto.Adapters.SQL.query!(TestRepo, "DELETE FROM things", [])

assert_receive {{Thing, :deleted}, %{id: ^already_existing_id1}}
assert_receive {:things_deleted, %{id: ^already_existing_id1}}

assert_receive {{Thing, :deleted}, %{id: ^already_existing_id2}}
assert_receive {:things_deleted, %{id: ^already_existing_id2}}
end

test "deletes for the primary key", %{
already_existing_id1: already_existing_id1,
already_existing_id2: already_existing_id2
Expand Down

0 comments on commit eff9e32

Please sign in to comment.