The problem
I have two schemas, coffees and orders wherein I want to get the recent completed order from each coffees
First solution
defmodule Schemas.Coffee do # ... more code has_many :completed_orders, Schemas.Order def coffee_query(coffee_id) do from c in __MODULE__, where: c.id == coffee_id, preload: [completed_orders: Orders.completed_order], limit: 1 end end defmodule Schemas.Order do # ... more code @completed_status :completed def completed_order_query() do from o in __MODULE__, where: o.status in ^@completed_status, order_by: [desc: o.updated_at] end end defmodule Contexts.Coffees do # more code def get_recent_completed_coffee_order(coffee_id) do coffee = coffee_id |> Schemas.Coffee.coffee_query() |> Repo.one List.first(coffee.completed_orders) end end Based from the setup, I can actually get the
completed_ordersof coffees but the only downside for me is that the preload will return alistSince it will return a
list, that will result into another process for me just to get the recent completed order.
Then, has_one/3 came into my life
defmodule Schemas.Coffee do # ... more code has_one :completed_order, Schemas.Order, where: [status: :completed], preload_order: [desc: :updated_at] def coffee_query(coffee_id) do from c in __MODULE__, where: c.id == ^coffee_id preload: [:completed_order], limit: 1 end end defmodule Contexts.Coffees do # more code def get_recent_completed_coffee_order(coffee_id) do coffee_id |> Schemas.Coffee.coffee_query() |> Repo.one |> Map.get(:completed_order, nil) end end What's the magic behind this scheme?
How does has_one/3 works?
Indicates a one-to-one association with another schema
From the current situation, coffee belongs_to order. As a result, coffee has_many orders, but I only need one result to return coming from the orders schema to identify if the coffee order is completed already.
Using has\_one/3\ I was able to achieve what I want.
has_one/3- indicates a one-to-one association with another schema.where- indicates aFiltering associationsto get my specific items.preload_order- Sets the defaultorder_byof the association, and since I am usinghas_one/3Ecto set a queryLIMITset toone.
[see has_one/3 on docs](https://hexdocs.pm/ecto/Ecto.Schema.html#has_one/3)
Happy Coding
Top comments (0)