API POST Not null violation Error. But the column value is in the request body

Hello, I’m a beginner with Phoenix and Elixir.

I’m building an API.

I used the mix command

phx.gen.json Mycontext MySchema myTable name:string start:datetime end:datetime user_id:references:users to build my different api routes.

this one is a one_to_many relationship with my users and the table myTable here.

So when i try a Post in my /api/mytable with post man. The application throw me this error :

Postgrex.Error at POST /api/mytable
ERROR 23502 (not_null_violation) a NULL value violates the NOT NULL constraint of the "user_id" column in the "mytable" relationship

    table: mytable
    column: user_id

The failed row contains (2, 2023-10-24 17:33:00, 2023-10-24 18:33:00, null, 2023-10-25 18:41:24, 2023-10-25 18:41:24).

the body of my request looks like this:

 {
    "mytable":{
        "start": "2023-10-24 17:33:00",
        "end": "2023-10-24 18:33:00",
        "user_id": 1
    }

I don’t understand this error, maybe the problem is due to the relationship?
Does anyone have any idea what going on?

Thanks a lot for your help !

Can you show us the generated schema module? And the relevant controller code?

1 Like

Your table name needs to be plural in order for the generators to properly do their thing. This is mentioned in the docs but doesn’t explain why (not sure it needs to but it’s easy to miss). See also here for recent discussion.

Here the generated schema :

defmodule TimeManager.Myschemas.Myschema do
  use Ecto.Schema
  import Ecto.Changeset

  schema "myschemas" do
    field :start, :naive_datetime
    field :end, :naive_datetime
    field :user_id, :id

    timestamps(type: :utc_datetime)
  end

  @doc false
  def changeset(myschema, attrs) do
    myschema
    |> cast(attrs, [:start, :end])
    |> validate_required([:start, :end])
  end
end

And the controller code :

def create(conn, %{"myschema" => myschema_params}) do
    with {:ok, %Myschema{} = myschema} <-
           Myschemas.create_myschema(myschema_params) do
      conn
      |> put_status(:created)
      |> put_resp_header("location", ~p"/api/myschemas/#{myschema}")
      |> render(:show, myschema: myschema)
    end
  end

Thanks for your reponse !

Sorry, I made a transcription mistake, my order for the generator is in plural.

phx.gen.json Mytables Mytable mytables name:string start:datetime end:datetime user_id:references:users 

That isn’t your schema, that’s the function in your context that inserts your item. Can you show the Myschema module?

sorry for my inattention,

This is mySchema:

defmodule TimeManager.Myschemas.Myschema do
  use Ecto.Schema
  import Ecto.Changeset

  schema "myschemas" do
    field :start, :naive_datetime
    field :end, :naive_datetime
    field :user_id, :id

    timestamps(type: :utc_datetime)
  end

  @doc false
  def changeset(myschema, attrs) do
    myschema
    |> cast(attrs, [:start, :end])
    |> validate_required([:start, :end])
  end
end

Right so in this case the issue is that :user_id is not on the list of fields you are casting. This is why it isn’t automatically handled from your request body.

2 Likes

it’s Working thanks you !