BeniaminoBaggins
BeniaminoBaggins

Reputation: 12433

Elixir - undefined function do_match/4

To refactor, I'm trying to move code out of my router into controllers.

I'm getting this error when I do so:

== Compilation error on file lib/api/controllers/product.ex == ** (CompileError) lib/plug/router.ex:211: undefined function do_match/4 (stdlib) lists.erl:1338: :lists.foreach/2 (stdlib) erl_eval.erl:670: :erl_eval.do_apply/6

controller

defmodule Api.Controllers.Product do 
    use Plug.Router
  import Api.ProductCategory
  alias Api.ProductCategory, as: ProductCategory
  import Api.Product
  import Api.Shop
  alias Api.Shop, as: Shop
  alias Api.Product, as: Product
  import Api.ProductShop
  alias Api.ProductShop, as: ProductShop
  import Api.Subcategory
  alias Api.Subcategory, as: Subcategory
  import Api.Category
  alias Api.Category, as: Category
  import Ecto.Query
  import Api.Repo

  def put_product(conn) do

    errors = {}
    # IO.inspect(conn.body_params)
    # IO.inspect(conn.query_params["p_id"])

    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.body_params["price"]

    product_shop = Api.Repo.get_by(ProductShop, s_id: sid, p_id: pid)
    IO.inspect(product_shop)

    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
end

router.ex

defmodule Api.Router do
  use Plug.Router
  import Api.ProductCategory
  alias Api.ProductCategory, as: ProductCategory
  import Api.Product
  import Api.Shop
  alias Api.Shop, as: Shop
  alias Api.Product, as: Product
  import Api.ProductShop
  alias Api.ProductShop, as: ProductShop
  import Api.Subcategory
  alias Api.Subcategory, as: Subcategory
  import Api.Category
  alias Api.Category, as: Category
  import Ecto.Query
  import Api.Controllers.Product
  alias Api.Controllers.Product, as: ProductController

  if Mix.env == :dev do
    use Plug.Debugger
  end
  plug :match
  plug Plug.Parsers, parsers: [:json],
                   pass:  ["application/json"],
                   json_decoder: Poison
  plug :dispatch

  get "/favicon.ico" do
    # get_categories(conn)
  end

  get "/categories/" do
    get_categories(conn)
  end

  options "/categories/" do
    get_categories(conn)
  end
....
  put "/products" do
    ProductController.put_product(conn)
  end
...

What is causing the error?

Full error:

Benjamins-MacBook-Pro:api Ben$ iex -S mix
Erlang/OTP 19 [erts-8.2] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Compiling 2 files (.ex)
warning: the variable "errors" is unsafe as it has been set inside a case/cond/receive/if/&&/||. Please explic
itly return the variable value instead. For example:

    case int do
      1 -> atom = :one
      2 -> atom = :two
    end

should be written as

    atom =
      case int do
        1 -> :one
        2 -> :two
      end

Unsafe variable found at:
  lib/api/controllers/product.ex:54

warning: the variable "errors" is unsafe as it has been set inside a case/cond/receive/if/&&/||. Please explic
itly return the variable value instead. For example:

    case int do
      1 -> atom = :one
      2 -> atom = :two
    end

should be written as

    atom =
      case int do
        1 -> :one
        2 -> :two
      end

Unsafe variable found at:
  lib/api/controllers/product.ex:56

warning: the variable "errors" is unsafe as it has been set inside a case/cond/receive/if/&&/||. Please explic
itly return the variable value instead. For example:

    case int do
      1 -> atom = :one
      2 -> atom = :two
    end

should be written as

    atom =
      case int do
        1 -> :one
        2 -> :two
      end

Unsafe variable found at:
  lib/api/controllers/product.ex:59
  lib/api/controllers/product.ex:59

warning: the variable "errors" is unsafe as it has been set inside a case/cond/receive/if/&&/||. Please explic
itly return the variable value instead. For example:

    case int do
      1 -> atom = :one
      2 -> atom = :two
    end

should be written as

    atom =
      case int do
        1 -> :one
        2 -> :two
      end

Unsafe variable found at:
  lib/api/controllers/product.ex:65

warning: variable "shop" is unused
  lib/api/controllers/product.ex:30

warning: variable "product" is unused
  lib/api/controllers/product.ex:38

warning: variable "changeset" is unused
  lib/api/controllers/product.ex:40

warning: variable "product_shop" is unused
  lib/api/controllers/product.ex:53

warning: variable "changeset2" is unused
  lib/api/controllers/product.ex:55


== Compilation error on file lib/api/controllers/product.ex ==
** (CompileError) lib/plug/router.ex:211: undefined function do_match/4
    (stdlib) lists.erl:1338: :lists.foreach/2
    (stdlib) erl_eval.erl:670: :erl_eval.do_apply/6

Upvotes: 0

Views: 913

Answers (1)

Dogbert
Dogbert

Reputation: 222040

You're getting the do_match error because your module uses Plug.Router but does not define any route. do_match function clauses are added by the get/post/etc macros in Plug.Router. With no routes, no function clause is ever defined causing that error. Since you don't actually want to define any routes in the module, you can just remove use Plug.Router.

You're also missing an import for the put_resp_content_type/2 function. Adding import Plug.Conn should fix that.

Upvotes: 1

Related Questions