在Elixir中定义自定义Maru类型并使用它来获取Json POST实体

时间:2016-11-30 09:46:40

标签: elixir maru

我想在Maru中定义一个自定义类型并使用它来解析JSON post实体,并进一步使用它来执行sql语句。但我不知道该怎么做。

这是我的自定义类型

defmodule Maru.Types.Volume do
  use Maru.Type

    @type length :: Float
    @type breadth :: Float
    @type height :: Float

end

此类型必须在路由器中使用

defmodule My.Router.Box do
   use Maru.Router
   alias My.Repo.Box, as: :DB

   namespace :select_volume do
      params do
         requires :volume, type: Volume

   post do
      volume = DB.getBoxWithRequiredVolume(params)
      conn |> put_status(200) |> json(volume)
   end
end

然后在这里用于sql查询

defmodule My.Repo.Box do
  import Ecto.Query
  require Logger

  def getBoxWithRequiredVolume(params) do
      volume = params[:volume]
      query = from box in My.Box,
          select: (
              %{id: box.id}
          ),
          where: (box.length == ^volume[:length] and box.breadth == ^volume[:breadth] and box.height == ^volume[:height])
      query |> My.Repo.all
  end
end

这是REST查询的实体:

http://localhost:8880/select_volume
{
 "volume":{
    "length": 20,
    "breadth": 5,
    "height": 5
 }
}

错误:

%Maru.Exceptions.InvalidFormatter{param: :volume, reason: :illegal,
value: %{"breadth" => 5, "height" => 5, "length" => 20}}

2 个答案:

答案 0 :(得分:1)

您需要的不是自定义类型,您只需要使用这样的参数:

params do
  requires :volume, type: Map do
    requires :length, type: Float
    requires :breadth, type: Float
    requires :height, type: Float
  end
end

然后,您可以从上面发送的请求中获取params%{breadth: 5.0, height: 5.0, length: 20.0}

答案 1 :(得分:0)

在Elixir中,

String s又名binariesAtom s不同。

您传递的值包含二进制文件作为键。格式化程序需要原子(例如:volume[:length])。

另外,我建议您对My.Repo.Box.getBoxWithRequiredVolume进行明确的测试,以确保它返回预期的内容。

旁注:抛出此特定异常的源代码可能会发光:它是Maru.Runtime.do_parse/3