xingxing liu
xingxing liu

Reputation: 3

Phoenix crate a RESTful API, error message: no function clause matching

I am learning how to use Phoenix to create RESTful API. My steps as follows:

step1: use mix task create database schema and some code

mix phx.gen.context AnimalAdmin Animal animal name:string email:string:unique role:string address:string

mix phx.gen.json AnimalAdmin Animal animal name:string email:string:unique role:string address:string --no-context --no-schema

step2: update my repository by running

mix ecto.migrate

step3: update router.ex file

pipe_through :api
get "/animal", AnimalController, :index
put "/animal", AnimalController, :edit
post "/animal", AnimalController, :create
delete "/animal", AnimalController, :delete

step4: start server

mix phx.server

The animal_controller.ex file is

defmodule InvestmentBackWeb.AnimalController do
  use InvestmentBackWeb, :controller

  alias InvestmentBack.AnimalAdmin
  alias InvestmentBack.AnimalAdmin.Animal

  action_fallback InvestmentBackWeb.FallbackController

  def index(conn, _params) do
    animal = AnimalAdmin.list_animal()
    render(conn, "index.json", animal: animal)
  end

  def create(conn, %{"animal" => animal_params}) do
    with {:ok, %Animal{} = animal} <- AnimalAdmin.create_animal(animal_params) do
      conn
      |> put_status(:created)
      # |> put_resp_header("location", Routes.animal_path(conn, :show, animal))
      |> render("show.json", animal: animal)
    end
  end

  def show(conn, %{"id" => id}) do
    animal = AnimalAdmin.get_animal!(id)
    render(conn, "show.json", animal: animal)
  end

  def update(conn, %{"id" => id, "animal" => animal_params}) do
    animal = AnimalAdmin.get_animal!(id)

    with {:ok, %Animal{} = animal} <- AnimalAdmin.update_animal(animal, animal_params) do
      render(conn, "show.json", animal: animal)
    end
  end

  def delete(conn, %{"id" => id}) do
    animal = AnimalAdmin.get_animal!(id)

    with {:ok, %Animal{}} <- AnimalAdmin.delete_animal(animal) do
      send_resp(conn, :no_content, "")
    end
  end
end

I want add a row data to my repository by phoenix RESTful API, and use postman as this

postman

When send a HTTP request, the response' code is 400, and error message is :

no function clause matching in InvestmentBackWeb.AnimalController.create/2

The following arguments were given to InvestmentBackWeb.AnimalController.create/2:

    # 1
    %Plug.Conn{adapter: {Plug.Cowboy.Conn, :...}, assigns: %{}, body_params: %{"address" => "china", "email" => "[email protected]", "name" => "xingxingliu", "role" => "new developer"}, cookies: %{}, halted: false, host: "localhost", method: "POST", owner: #PID<0.555.0>, params: %{"address" => "china", "email" => "[email protected]", "name" => "xingxingliu", "role" => "new developer"}, path_info: ["animal"], path_params: %{}, port: 4000, private: %{InvestmentBackWeb.Router => {[], %{Plug.Swoosh.MailboxPreview => ["mailbox"]}}, :before_send => [#Function<0.11807388/1 in Plug.Telemetry.call/2>, #Function<1.86886788/1 in Phoenix.LiveReloader.before_send_inject_reloader/3>], :phoenix_action => :create, :phoenix_controller => InvestmentBackWeb.AnimalController, :phoenix_endpoint => InvestmentBackWeb.Endpoint, :phoenix_format => "json", :phoenix_layout => {InvestmentBackWeb.LayoutView, :app}, :phoenix_request_logger => {"request_logger", "request_logger"}, :phoenix_router => InvestmentBackWeb.Router, :phoenix_view => InvestmentBackWeb.AnimalView, :plug_session_fetch => #Function<1.84243074/1 in Plug.Session.fetch_session/1>}, query_params: %{}, query_string: "", remote_ip: {127, 0, 0, 1}, req_cookies: %{}, req_headers: [{"accept", "*/*"}, {"accept-encoding", "gzip, deflate, br"}, {"connection", "keep-alive"}, {"content-length", "118"}, {"content-type", "application/json"}, {"host", "localhost:4000"}, {"postman-token", "5528ed3e-d8de-4e2e-82e3-2d7b1b3bde39"}, {"user-agent", "PostmanRuntime/7.31.3"}], request_path: "/animal", resp_body: nil, resp_cookies: %{}, resp_headers: [{"cache-control", "max-age=0, private, must-revalidate"}, {"x-request-id", "F0-VSsiF-LxMK_gAAAAC"}], scheme: :http, script_name: [], secret_key_base: :..., state: :unset, status: nil}

    # 2
    %{"address" => "china", "email" => "[email protected]", "name" => "xingxingliu", "role" => "new developer"}

I don't why problem appear. I will be greatly appreciated someone points out.

the elixir version:

Erlang/OTP 25 [erts-13.1.1] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit] [dtrace]

Elixir 1.14.2 (compiled with Erlang/OTP 25)

the phoenix version is 1.6.16

Upvotes: 0

Views: 192

Answers (1)

Dogbert
Dogbert

Reputation: 222198

The generated Phoenix Controller expects the Animal data to be inside the key "animal", not at the top level. You can fix this by modifying your Postman request to have the body like this:

{
  "animal": {
    "name": "something",
    "email": "...",
    ...
  }
}

Upvotes: 1

Related Questions