TokenOperator - Dependency-free helper most commonly used for making clean keyword APIs to Phoenix context functions

By the way, I’ve continued with the method of passing context functions, but have moved to about as explicit method as you can get. Previously, I was passing a list of public functions that will later be run in succession as if they were piped like so…

# controller

  Accounts.list_users([
    &Accounts.join_user_profile/1,
    &Accounts.filter_non_executive_users/1,
    &Accounts.filter_users_by_company(&1, company),
    &Accounts.order_users_by_first_name/1
  ])

# context

def list_users(queries \\ []) do
  from(User)
  |> QueryRunner.run(queries)
  |> Repo.all()
end

# QueryRunner utility

defmodule Utilities.QueryRunner do
  def run(query, additional_queries) when is_list(additional_queries) do
    Enum.reduce(additional_queries, query, fn additional_query, query ->
      additional_query.(query)
    end)
  end

  def run(query, additional_query) do
    run(query, [additional_query])
  end
end

However, since all we really want to do is inject into the context query and run as piped, why not just pass an anonymous function that is piped in the first place?

# controller

Accounts.list_users(
  &(Accounts.join_user_profile(&1)
    |> Accounts.filter_non_executive_users()
    |> Accounts.filter_users_by_company(company)
    |> Accounts.order_users_by_first_name())
)

# context

def list_users(queries \\ &(&1)) do
  from(User)
  |> queries.()
  |> Repo.all()
end

This requires no additional code and is more obvious to me anyway. Using fn over capture is arguably more readable, but that just comes down to preference.

# controller

Accounts.list_users(fn query ->
  query
  |> Accounts.join_user_profile()
  |> Accounts.filter_non_executive_users()
  |> Accounts.filter_users_by_company(company)
  |> Accounts.order_users_by_first_name()
end)
1 Like