【问题标题】:Phoenix: API controller gets error regardless of paramsPhoenix:无论参数如何,API 控制器都会出错
【发布时间】:2017-09-05 13:25:37
【问题描述】:

我有一个如下所示的控制器:

defmodule PrefectWeb.DocumentController do
  use PrefectWeb, :controller

  alias Prefect.Queue

  def create(conn, params) do
    case Prefect.add(Queue, struct(Prefect.Document, params[:id])) do
      nil -> conn 
        |> put_status(404) 
        |> render("error.json")
      status -> {:ok, status}
    end
  end
end

create 方法应该将params[:id] 添加到Queue 进程中。我的单元测试如下所示:

defmodule PrefectWeb.DocumentControllerTest do
  use ExUnit.Case, async: true
  use PrefectWeb.ConnCase

  setup do
    params = [
      env: "test",
      id: 1,
    ]

    [params: params]
  end

  test "creation", %{conn: conn, params: params} do
    conn
    |> post(document_path(conn, :create, params))

    assert json_response(conn, 422)
  end
end

此规范返回此错误:

1) test creation (PrefectWeb.DocumentControllerTest)
   test/prefect_web/controllers/document_controller_test.exs:27
   ** (Protocol.UndefinedError) protocol Enumerable not implemented for nil. This protocol is implemented for: Date.Range, File.Stream, Function, GenEvent.Stream, HashDict, HashSet, IO.Stream, List, Map, MapSet, Range, Stream

如果我将控制器功能更改为他的:

def create(conn, %{"params" => params}) do
  ...
end

我收到此错误:

1) test creation (PrefectWeb.DocumentControllerTest)
     test/prefect_web/controllers/document_controller_test.exs:27
     ** (Phoenix.ActionClauseError) could not find a matching PrefectWeb.DocumentController.create clause
     to process request. This typically happens when there is a
     parameter mismatch but may also happen when any of the other
     action arguments do not match. The request parameters are:

       %{"env" => "test", "id" => "1"}

为什么我不能正确地将params[:id] 传递给create 方法?

更新

添加请求标头也无济于事:

|> put_req_header("content-type", "application/json")

【问题讨论】:

    标签: elixir phoenix-framework


    【解决方案1】:

    参数映射是字符串而不是基于原子的。尝试将您的控制器更改为

    defmodule PrefectWeb.DocumentController do
      use PrefectWeb, :controller
    
      alias Prefect.Queue
    
      def create(conn, params) do
        case Prefect.add(Queue, struct(Prefect.Document, params["id"])) do
          nil -> conn 
            |> put_status(404) 
            |> render("error.json")
          status -> {:ok, status}
        end
      end
    end
    

    和你的测试

    defmodule PrefectWeb.DocumentControllerTest do
      use ExUnit.Case, async: true
      use PrefectWeb.ConnCase
    
      setup do
        params = %{
          "env" => "test",
          "id" => 1
        }
    
        [params: params]
      end
    
      test "creation", %{conn: conn, params: params} do
        conn
        |> post(document_path(conn, :create, params))
    
        assert json_response(conn, 422)
      end
    end
    

    【讨论】:

    • 啊!谢谢。这有点令人困惑,哈。
    【解决方案2】:

    您正在断言在setup 中创建的连接,而不是从post 返回的连接。尝试在断言之前重新绑定conn

      test "creation", %{conn: conn, params: params} do
        conn = 
          conn
          |> post(document_path(conn, :create), params)
    
        assert json_response(conn, 422)
      end
    

    【讨论】:

    • 这会导致错误** (Protocol.UndefinedError) protocol Enumerable not implemented for nil.
    • 啊,很好,但这将我们带到了我最初遇到的另一个错误。
    猜你喜欢
    • 1970-01-01
    • 2015-09-22
    • 2010-12-04
    • 2022-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-22
    • 1970-01-01
    相关资源
    最近更新 更多