Is it necessary to have the model name in the request params (for security reasons or whatnot)?

User controller:

def create(conn, %{"user" => user_params}) do

The problem with this is that user_params is not decoded from JSON to map. So when it reaches the creation of the changeset:

changeset = User.changeset(%User{}, user_params)

This part will fail because user_params is expected to be a map and not a string.

There are a few workarounds to this. The user_params key can be removed and just pass the actual params. The signature would now look like this:

def create(conn, %{"name" => name, "email" => email}) do

Then you’ll have to create this:

user_params = %{"name" => name, "email" => email}) do

Or you can just do this:

def create(conn, user_params) do

Or you can use the original create signature and just decode user_params manually using Poison.

I thought it would be automatically decoded to a map. I’m trying to find out what is the idiomatic way of doing this.

Eh, that’s weird. The request params should be decoded when going through your app’s Endpoint. There’s this line in lib/yourapp/endpoint.ex that should do just that:

plug Plug.Parsers,
  parsers: [:urlencoded, :multipart, :json],
  pass: ["*/*"],
  json_decoder: Poison

Perhaps there’s something wrong in the way you’re sending the data (headers etc.)?