Rendering Ecto structs has been a major pain point for me. Any help is greatly appreciated.
Given an Orders schema with a belongs_to relation to Customer, and a many_to_many relation to Product, how do I go about rendering these associations using Jason? I can’t simply do something like this:
defp data(%Order{} = order) do
order
end
because Jason complains that this struct hasn’t implemented the Jason.Encoder protocol.
I could simply make the schemas implement the protocol, but I’ve done this before and if you end up changing a structure of the struct in any way you’re back to the start.
Ideally, I would like the metadata of the struct (e.g., __struct__
, __meta__
, any keys with the value of Ecto.Association.NotLoaded
) to get filtered out automatically.
I ended up creating this abomination:
defp data(%Order{} = order) do
customer = Map.get(order, :customer)
customer =
if not is_struct(customer, Ecto.Association.NotLoaded) do
%{
id: customer.id,
name: customer.name,
delivery_address: customer.delivery_address
}
end
products = Map.get(order, :products)
products =
if not is_struct(products, Ecto.Association.NotLoaded) do
for product <- order.products do
%{
id: product.id,
name: product.name,
price: product.price
}
end
end
%{
id: order.id,
payment_method: order.payment_method,
notes: order.notes,
status: order.status,
customer: customer,
products: products
}
end
Is there a way most people handle this issue?