A few noob questions here - sorry. (I am making my way through the Udemy course and I also bought the Programming Phoenix and Elixir books, but it would be satisfying if I could get this JSON outputting as intended in the meantime and understand how it’s done.)
Query example:
/api/banner_price?material_id=2&width=1000&height=2200
Controller:
defmodule AppName.Api.BannerPriceController do
use AppName.Web, :controller
alias AppName.Product.Material
defp unit_mm(x) do x <> "mm" end
defp calculate_price(price_sq_m, width, height) do
Money.multiply(price_sq_m, width * height / 1000000)
end
def show(conn, %{"material_id" => material_id, "width" => width, "height" => height}) do
material = Repo.get!(Material, material_id)
|> Map.take([:id, :price_sq_m, :name])
# |> Access.get_and_update()
# put_in(material, [:price_sq_m], material.price_sq_m |> Money.to_string(symbol: true))
price = calculate_price(material.price_sq_m, String.to_integer(width), String.to_integer(height))
|> Money.to_string(symbol: true)
dims = Enum.map([width, height], fn(x) -> unit_mm(x) end)
render(conn, "banner_price.json", %{dims: dims, material: material, price: price})
end
end
View:
defmodule AppName.Api.BannerPriceView do
use AppName.Web, :view
def render("banner_price.json", %{dims: dims, material: material, price: price}) do
%{type: "banner prices", material: material, price: price, dimensions: dims}
end
end
JSON result:
{
"type": "banner prices",
"price": "£23.10",
"material": {
"price_sq_m": {
"currency": "GBP",
"amount": 1050
},
"name": "440gsm PVC",
"id": 2
},
"dimensions": [
"1000mm",
"2200mm"
]
}
My questions:
- Is using
String.to_integer()
like this an appropriate way to use number values in URL query parameters? - How can I replace the
price_sq_m
part of thematerial
part of the JSON with"Price per square metre": "£10.50"
? (I believe the ‘£10.50’ itself can be achieved withMoney.to_string(material.price_sq_m, symbol: true)
, but I’m struggling to replace the relevant key and value.) - How can I wrap all of the JSON in a containing ‘data’ attribute/containing “node”? I think this will involve adding another
render
function to the view, but I’ve been failing hard when it comes to that.
(If you see any issues or improvements that can be made with any of the code I’d be glad to hear them, too, of course. )
Thanks.