Piping Phoenix Contexts

Image for post
Image for post
Photo by tian kuan on Unsplash

The Study Case

BookStore
- Account (context)
- schema:
- User
- public functions:
- get_user(id :: integer()) :: User.t() | nil
- Library (context)
- schema:
- Book
- public functions:
- get_books_with_promotion(book_ids :: [integer()]) :: [Book.t()] | nil
- Shop (context)
- schema:
- Order
- Item
- Coupon
- public functions:
- get_order(id :: integer()) :: Order.t() | nil
- apply_discount(Order.t(), discount_value :: integer()) :: {:ok, Order.t()} | {:error, any()}
- get_coupon_by_code(promo_code :: binary()) :: Coupon.t() | nil
- use_coupon(Coupon.t()) :: {:ok, Coupon.t()} | {:error, any()}

Implement a new discount coupon

Implementation

1. Where would this code live?

Pipeline
- ApplyCoupon
BookStore
- Account
- Library
- Shop

2. Cannot support multiple happy paths

%Coupon{used: false} = coupon <- get_coupon(promo_code)
else
%Coupon{} -> {:ok, order} #order is not available

3. Cryptic error messages

Inter-contextual Pipelines

The Pipeline Rules

Advantages

Caveats

Image for post
Image for post

elixir dev | dorian.iacobescu@gmail.com | @iac0bs0n

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store