rubynho
Any idea of what code to put in the domain's main file
Context
Generating a phoenix app with name foo, an empty module will be created in the foo/lib/foo.ex file like so:
defmodule Foo do
@moduledoc """
Foo keeps the contexts that define your domain
and business logic.
Contexts are also responsible for managing your data, regardless
if it comes from the database, an external API or others.
"""
end
That is what I’m calling the main file.
Question
What code do you put in there or any idea of what could fit?
In my mind it makes sense to put functions that use other functions from the contexts modules to deliver a complete service/feature of the system (e.g. user registration). For example:
defmodule Foo do
alias Foo.Accounts
def register_user(params)
case Accounts.register_user(params) do
{:ok, user} ->
Accounts.deliver_user_confirmation_instructions(
user,
&Path.join(params["confirmation_url"], &1)
)
{:ok, user}
{:error, _} = error ->
error
end
end
end
See any cons about this idea?
Marked As Solved
sodapopcan
To me the functions that would most naturally live here are delegates to every single public function in your domain. This is pretty heavy-handed, though, and I wouldn’t recommend it—I tried it! Otherwise, what you’re suggesting at the very least hurts discoverability. If you think of it from the perspective of someone coming in and only reading the business domain code, there will be auth functions spread out over different context boundaries. I don’t think it’s the worst thing in the world, but to me I would just think there is no point—just add a function to Accounts called register_and_notify_user. I would also change the signature to take user_attrs and confirmation_url separately.
Really in a Phoenix app, I think the best use of this module is documentation. I’m sure there is something that could naturally fit here, but I’ve never come across anything. I think a lot of people get perturbed that this file sits there devoid of code. It doesn’t personally bother me. If you use ex_doc on your project it certainly comes in handy!
Also Liked
tomkonidas
I personally like to use it similar to the way Phoenix does it with the FooWeb module; As a place to define macros for your app.
A good example would be something like:
defmodule Foo.Accounts.User do
use Foo, :schema
schema "users" do
# ...
end
end
Which Foo can have something like:
defmodule Foo do
def schema do
quote do
use Ecto.Schema
import Ecto.Changeset
@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id
@timestamps_opts [type: :utc_datetime_usec]
end
end
defmacro __using__(which) when is_atom(which) do
apply(__MODULE__, which, [])
end
end
kokolegorille
There is this package that does CQRS/ES
I did my own event store…
https://github.com/kokolegorille/event_store
and a simple demo usage
https://github.com/kokolegorille/microservices_umbrella
This allows me to decouple context… instead of doing
def register_user(...) do
do_work()
deliver_user_confirmation_instructions()
notify_by_email()
end
I do
def register_user(...) do
do_work()
EventStore.create_event(...)
end
Any context can listen to any event…
register_user() does not need to know what to do when a user register
Adding functionalities is easier, because it does not affect previous code
When You create an event, it is dispatched to listeners
def dispatch(event) do
Logger.info("DISPATCH EVENT : #{inspect(event)}")
ListenersProvider.get_listeners()
|> Enum.filter(fn {_pid, filter_fun} -> filter_fun.(event) end)
|> Enum.each(fn {pid, _apply_fun} -> send(pid, event) end)
:ok
end
cevado
I usually move whatever is on Foo.Application to Foo and update my mix.exs file to reflect that.
if it’s a phoenix app i usually rename FooWeb to be only Web and I rename the remaining stuff in the foo folder to be core and have a Core namespace.
but that’s because i really don’t how namespaces work in the default generators for plain mix or phoenix.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance










