0

In my free time I am learning elixir, and now I am trying to develop simple Elixir API. Everything works fine, besides when I try to insert new values using Postman/curl. When I'm trying to do so with such data:

{
    "tree": "nil",
    "value": "5"
}

I get this error: (FunctionClauseError) no function clause matching in Access.get/3.

Here is my code for POST in my Endpoint.

post "/insert" do
    IO.inspect(conn.body_params)
    {status, body} =
      case conn.body_params do
        %{"tree" => tree, "value" => value} -> {200, process_insert(tree, value)}
        BstInsertion.insert(tree, value)
        _ -> {400, missing_insert()}
      end

    send_resp(conn, status, body)
  end

Example of insert function and process_insert:

  def insert(nil, value) do
    %{value: value, ltree: nil, rtree: nil}
  end

  defp process_insert(_tree, _value) do
    Poison.encode!(%{response: "Received insert!"})
  end

If this is not enough, I will provide more code. Thank you for any advice and help.

Kapeusz
  • 61
  • 7
  • The error you are seeing is because you are calling the `Access.get/3` function with the wrong arguments. Is it a function you wrote? I don't see any code that makes a call that function. – Christophe De Troyer Oct 20 '21 at 16:13
  • @ChristopheDeTroyer Isn't Access.get/3 an Elixir built-in function? I did not write anywhere Access.get/3 function. – Kapeusz Oct 20 '21 at 16:18
  • I think their point was the code you show us doesn't include any calls to `Access.get/3`. Is it perhaps in your `process_insert/2` function? – Brett Beatty Oct 20 '21 at 17:04
  • @BrettBeatty Please, check updated question. I attached relevant code for this function. – Kapeusz Oct 20 '21 at 17:08
  • It would go to another clause of your `insert/2` function because `tree` has the value `"nil"`, not `nil`. You may in your request want to pass `"tree": null` in your JSON if I'm understanding your intent. Your next clause may expect an existing `tree` when it's just the string "nil". You'll next run into problems where `{status, body}` is not returned from the first clause in your `case`: it instead returns the result of `insert/2`, which appears to be a map representing your tree. – Brett Beatty Oct 20 '21 at 17:25
  • @BrettBeatty You are right. When I changed nil to null i got new error. This time it is`no match of right hand side value: %{ltree: nil, rtree: nil, value: 5}` but I still don't know how to get rid of these errors... – Kapeusz Oct 20 '21 at 17:37
  • Elixir returns the last expression in a block, so your success case does nothing with `{200, process_insert(tree, value)}` (it'll call `process_insert/2`, but you aren't doing anything with it, so the `{200, ~S({"response": "Received insert!"})}` gets thrown out). Instead what the success case returns is the result of `BstInsertion.insert(tree, value)`, which is a map and not the `{status, body}` tuple you're attempting to match. The first step in my mind would be to swap the two lines so you're returning a `{status, body}` tuple. – Brett Beatty Oct 20 '21 at 19:32
  • Then it's up to you to decide what the controller actually does. If it's supposed to update server state, you can do that, or if you're trying to return the new tree, you can pass the new tree into the function that creates your response body. Something like `new_tree = BstInsertion.insert(tree, value)` then `{200, Poison.encode!(%{tree: new_tree})}` – Brett Beatty Oct 20 '21 at 19:35

1 Answers1

0

I think you have a problem in your code. I have tidied up your code a bit:

post "/insert" do
  IO.inspect(conn.body_params)
  {status, body} =
    case conn.body_params do
      %{"tree" => tree, "value" => value} ->
        {200, process_insert(tree, value)}
        BstInsertion.insert(tree, value) # What is this line? What is the output?
        
      _ ->
        {400, missing_insert()}
    end

  send_resp(conn, status, body)
end

The last line in each clause/function is the return value. So your first case clause returns the value of BstInsertion.insert(tree, value). Is that what you expect? From the previous line, I can say it is not.

vfsoraki
  • 2,186
  • 1
  • 20
  • 45