我有一个将产品添加到数据库的功能(product
是map
):
@derive {Poison.Encoder, only: [:s_id, :p_id]}
schema "product_shops" do
field :s_id, :integer
field :p_id, :integer
field :not_in_shop_count, :integer
field :price, :float
end
def changeset(product_shop, params \\ %{}) do
product_shop
|> cast(params, [:s_id, :p_id, :price, :not_in_shop_count])
|> validate_required([:s_id, :p_id])
|> unique_constraint(:s_id, name: :unique_product_shop)
end
def insert_product_shop(conn, product_id, shop_id, price) do
IO.inspect(price, label: "price")
changeset = Api.ProductShop.changeset(%Api.ProductShop{p_id: product_id, s_id: shop_id, not_in_shop_count: 0, price: price})
errors = changeset.errors
valid = changeset.valid?
case insert(changeset) do
{:ok, product_shop} ->
{:ok, product_shop}
{:error, changeset} ->
{:error, :failure}
end
end
IO.inspect显示:
price: 52
但是我收到了这个错误:
(Ecto.ChangeError) value `24` for `Api.ProductShop.price` in `insert` does not match type :float
所以价格是int
,但需要是float
。
这是来自IO.inspect(product)
%{"brand" => "if",
"categories" => [%{"categoryId" => 1, "label" => "Meat",
"selectedAdd" => true, "selectedSearch" => false, "value" => 1}],
"description" => "kcjcufujdifgkv. ckcfickc", "name" => "car",
"not_vegan_count" => 0, "number_of_votes" => 0, "price" => 24,
"rating" => nil,
"shop" => %{"latitude" => -37.6739483, "longitude" => 176.1662587,
"name" => "Rebel Sport", "place_id" => "ChIJgRN1iu_bbW0Rsb-fET0z81Y"}}
将价格转换为浮动尝试(using this resource):
def insert_product(conn, product) do
IO.puts("the product price")
IO.inspect(Map.fetch(product, "price"))
%{product | "price" => "price" / 1}
IO.puts("the product price as a float")
IO.inspect(Map.fetch(product, "price"))
记录下来:
the product price
{:ok, 24}
有错误:
** (ArithmeticError) bad argument in arithmetic expression
如何让price
中的map
成为float
?
答案 0 :(得分:2)
回答所述问题:
iex(1)> map = %{"foo" => 42}
%{"foo" => 42}
iex(2)> %{map | "foo" => map["foo"] / 1}
%{"foo" => 42.0}
请注意,在Elixir术语中所有不可变,因此甚至是正确的条款:
%{product | "price" => product["price"] / 1}
是NOOP。结果立即被丢弃。必须重新绑定product
以便以后使用它:
product = %{product | "price" => product["price"] / 1}
一般情况下应该使用Ecto.Changeset.cast/4
,而不是明确。
如果出于某种原因需要手动转换值,Ecto.Type.cast/2
可以解决问题:
Ecto.Type.cast(:float, 1)
#⇒ 1.0
旁注: IO.inspect/2
接受第二个参数opts
:
IO.inspect(product, label: "the product")