2017-07-15 16 views
0

我越來越想更新與變更的記錄時,此錯誤:外生 - 更新記錄 - 未定義功能__changeset __/0

14:36:29.972 [error] #PID<0.341.0> running Api.Router terminated 
Server: 192.168.20.3:4000 (http) 
Request: PUT /products/?p_id=11&s_id=11 
** (exit) an exception was raised: 
    ** (UndefinedFunctionError) function Ecto.Query.__changeset__/0 is undefined or private 
     (ecto) Ecto.Query.__changeset__() 
     (ecto) lib/ecto/changeset.ex:422: Ecto.Changeset.do_cast/4 
     (api) lib/api/product_shop.ex:17: Api.ProductShop.changeset/2 
     (api) lib/api/router.ex:168: anonymous fn/1 in Api.Router.do_match/4 
     (api) lib/api/router.ex:1: Api.Router.plug_builder_call/2 
     (api) lib/plug/debugger.ex:123: Api.Router.call/2 
     (plug) lib/plug/adapters/cowboy/handler.ex:15: Plug.Adapters.Cowboy.Handler.upgrade/4 
     (cowboy) /Users/Ben/Development/Projects/vepo/api/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protoco 
l.execute/4 

代碼:

pid = conn.query_params["p_id"] 
sid = conn.query_params["s_id"] 
price = conn.query_params["price"] 
query = ProductShop |> Ecto.Query.where(p_id: ^pid) 
product_shop = query |> Ecto.Query.where(s_id: ^sid) 

changeset2 = Api.ProductShop.changeset(product_shop, %{price: price}) 
case Api.Repo.update(changeset2) do 
    {:ok, product_shop} -> 
    errors = Tuple.append(errors, "Price updated") 
    {:error, changeset2} -> 
    errors = Tuple.append(errors, "Price not updated") 
end 

這是ProductShop我想更新:

14:38:56.658 [debug] QUERY OK source="product_shops" db=1.7ms 
SELECT p0."id", p0."s_id", p0."p_id", p0."not_in_shop_count", p0."price" FROM "product_shops" AS p0 [] 
[%Api.ProductShop{__meta__: #Ecto.Schema.Metadata<:loaded, "product_shops">, 

    id: 11, not_in_shop_count: 0, p_id: 11, price: 5.99, s_id: 11}] 

爲什麼我會收到錯誤?

ProductShop文件,變更:

defmodule Api.ProductShop do 
    use Ecto.Schema 
    import Ecto.Changeset 
    import Api.Repo 
    import Ecto.Query 

    @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]) 
    |> 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 
    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 

    def delete_all_from_product_shops do 
    from(Api.ProductShop) |> delete_all 
    end 

    def get_product_shops do 
    Api.ProductShop |> all 
    end 
end 

router.ex

put "/products" do 
    errors = {} 
    IO.inspect(conn.body_params) 

    product = Api.Product |> Api.Repo.get(conn.query_params["p_id"]) 
    shop = Api.Shop |> Api.Repo.get(conn.query_params["s_id"]) 

    params = for key <- ~w(image description), value = conn.body_params[key], into: %{}, do: {key, value} 
    changeset = Api.Product.changeset(product, params) 
    case Api.Repo.update(changeset) do 
     {:ok, product} -> 
     errors = Tuple.append(errors, "Product updated") 
     {:error, changeset} -> 
     errors = Tuple.append(errors, "Product not updated") 
    end 

    pid = conn.query_params["p_id"] 
    sid = conn.query_params["s_id"] 
    price = conn.query_params["price"] 
    query = ProductShop |> Ecto.Query.where(p_id: ^pid) 
    product_shop = query |> Ecto.Query.where(s_id: ^sid) 

    changeset2 = Api.ProductShop.changeset(product_shop, %{price: price}) 
    case Api.Repo.update(changeset2) do 
     {:ok, product_shop} -> 
     errors = Tuple.append(errors, "Price updated") 
     {:error, changeset2} -> 
     errors = Tuple.append(errors, "Price not updated") 
    end 

    IO.inspect(errors) 

    conn 
     |> put_resp_content_type("application/json") 
     |> send_resp(200, Poison.encode!(%{ 
      successs: "success", 
      errors: Tuple.to_list(errors) 
     })) 
    end 

回答

1

外生的changeset功能,你在寫模式,默認情況下作品Ecto.Schema,這意味着它適用於在其中定義模式的模塊。使用cast後,它處理Ecto.Changeset結構。

你的代碼試圖在變更功能與Ecto.Query工作,即在這裏:

product_shop = query |> Ecto.Query.where(s_id: ^sid) 

你應該在年底使用Repo.one()有有效ProductShop結構,然後你可以在ProductShop.changeset功能使用它。

另外考慮重寫你想如何檢索這個product_shop。請使用Repo.get_by

Repo.get_by(ProductShop, s_id: s_id, p_id: p_id)