stevegrossi / habits

An Elixir/Phoenix app for tracking daily habits, ready to deploy to Heroku.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

assoc vs. ids: should contexts reach into other contexts?

stevegrossi opened this issue Β· comments

assoc

def list_habits(%Account{} = account) do
  account
  |> assoc(:habits)
  |> Repo.all()
end
  • Requires import Ecto, only: [assoc: 2]
  • πŸ‘Ž Pattern-matching (optional, but ideal) requires reference to another context's schema, Accounts.Account

ids

def list_habits(account_id) when is_integer(account_id) do
  account
  |> where(account_id: ^account_id)
  |> Repo.all()
end
  • Requires import Ecto.Query
  • πŸ‘ A tiny bit more efficient, since we only need the ID from the database, not the full record
  • πŸ‘Ž Requires duplicating (potentially complex, with joins) relationship logic

In-Context associations?

Inspired by this forum post.

def list_habits(account_id) when is_integer(account_id) do
  %Habits.Account{id: account_id} # not Accounts.Account
  |> assoc(:habits)
  |> Repo.all()
end

# which requires

defmodule Habits.Habits.Account do
  use Ecto.Schema

  schema "accounts" do
    has_many(:habits, Habit)
  end
end
  • πŸ‘ Avoids potential duplication of the account <-> habits association logic within this context
  • πŸ‘ Habits.Account could be anything, potentially more context-specific like Habits.Owner
  • πŸ‘ A tiny bit more efficient, since we only need the ID from the database, not the full record
  • πŸ‘Ž Another file?

I'm very curious about the "In-Context associations?" option, which seems to fulfill the promise of bounded contexts (though I know Phoenix contexts aren't explicitly an implementation of DDD's bounded context pattern). In that direction, it would be interesting to have a rule that no context may reference modules within another context. I like that idea in theory, I'm just curious how it would play out in practice.

This post details an interesting approach similar to "In-Context associations", but instead of only passing IDs between contexts, you can also pass _map_s (but not structs, which are domain-specific) between contexts.