Ecto Observable
Ecto Observable adds “observable” functionality to Ecto.Repo
.
Installation
The package can be installed by adding ecto_observable
to your list of dependencies in mix.exs
:
def deps do
[
{:ecto_observable, "~> 0.3.1"}
]
end
Documentation
See HexDocs for additional documentation.
Getting Started
Lets say we have a Post
schema. Each post can have many topics. Users can subscribe to topics. Whenever a post is created, we are responsible for informing the subscribed users.
Given the above, lets setup our new “observable” repo.
defmodule Repo do
use Ecto.Repo, otp_app: :my_app
use Observable.Repo
end
We have defined our repo as normal - but with the addition of use Observable.Repo
to bring in the required observable functionality.
Lets create our new observer now.
defmodule SubscribersObserver do
use Observable, :observer
# Lets ignore posts that dont have any topics.
def handle_notify({:insert, %Post{topics: []}}) do
:ok
end
def handle_notify({:insert, %Post{topics: topics}}) do
# Do work required to inform subscribed users.
end
# Defined for the sake of example. Ignore me!
def handle_notify({:update, [old_post, new_post]}) do
:ok
end
# Defined for the sake of example. Ignore me!
def handle_notify({:delete, post}) do
:ok
end
end
Now that we have our observer set up, lets modify our Post schema to support notifying our observers.
defmodule Post do
use Ecto.Schema
use Observable, :notifier
schema "posts" do
field(:title, :string)
field(:body, :string)
field(:topics, {:array, :string}, default: [])
end
observations do
action(:insert, [SubscribersObserver])
action(:update, [SubscribersObserver])
action(:delete, [OtherObserverOne, OtherObserverTwo]) # Defined for the sake of example.
end
end
Now that we are starting to use “observable” behaviour, we must modify the way in which we insert posts with our repo.
def create_post(params \\ %{}) do
%Post{}
|> Post.changeset(params)
|> Repo.insert_and_notify()
end
Our users will now be informed of any new posts with topics they are interested in!
The same behaviour can be replicated for :update
and :delete
actions.
Repo.update_and_notify(post)
Repo.delete_and_notify(post)
Each of the new observer-based actions also has equivalent bang function available that will raise on error.
Repo.insert_and_notify!(post)