(Ecto.ChangeError)值xxx for xxx与type:float不匹配

时间:2017-12-06 06:10:51

标签: elixir ecto

我有一个将产品添加到数据库的功能(productmap):

  @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

1 个答案:

答案 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")