0
votes

I've been stuck with a casting error with naivedatetime. Could someone unlock me please?

This is the POST request i'm trying to do: URL: http://localhost:4000/api/workingtimes/1

Body:

{ "start": "2019-08-21 07:27:00", "end": "2020-09-20 07:27:00" }

Here is my schema:

 defmodule TimeManager.Workingtimes.Workingtime do
  use Ecto.Schema
  import Ecto.Changeset

  schema "workingtimes" do
    field :start, :naive_datetime
    field :end, :naive_datetime
    belongs_to :user, TimeManager.Users.User

    timestamps()
  end

  @doc false
  def changeset(workingtime, attrs) do
    workingtime
    |> cast(attrs, [:start, :end, :user_id])
    |> validate_required([:start, :end, :user_id])
    |> assoc_constraint(:user)
  end
end

And here is my create function in the controller:

  def create(conn, workingtime_params) do
    with {:ok, %Workingtime{} = workingtime} <- Workingtimes.create_workingtime(workingtime_params) do
      conn
      |> put_status(:created)
      |> put_resp_header("location", Routes.workingtime_path(conn, :show, workingtime))
      |> render("workingtime.json", workingtime: workingtime)
    end
  end

finally here is my create_workingtime function in my workingtimes.ex

  def create_workingtime(attrs \\ %{}) do
    %{"start" => starttime, "end" => endtime, "user_id"=>user_id } = attrs
    {:ok, naivestart} = NaiveDateTime.from_iso8601(starttime)
    {:ok, naiveend} = NaiveDateTime.from_iso8601(endtime)
    attrs = %{"start" => naivestart, "end"=>naiveend, "user_id"=>user_id}
  
    Workingtime
    |> Workingtime.changeset(attrs)
    |> Repo.insert()
  end

The error in the log is:

  • (exit) an exception was raised: ** (FunctionClauseError) no function clause matching in Ecto.Changeset.cast/4 (ecto 3.5.2) lib/ecto/changeset.ex:461: Ecto.Changeset.cast(TimeManager.Workingtimes.Workingtime, %{"end" => ~N[2020-10-21 19:45:24.879000], "start" => ~N[2020-10-21 19:45:24.879000], "user_id" => "1"}, [:start, :end, :user_id], []) (time_manager 0.1.0) lib/time_manager/workingtimes/workingtime.ex:16: TimeManager.Workingtimes.Workingtime.changeset/2 (time_manager 0.1.0) lib/time_manager/workingtimes.ex:63: TimeManager.Workingtimes.create_workingtime/1 (time_manager 0.1.0) lib/time_manager_web/controllers/workingtime_controller.ex:16: TimeManagerWeb.WorkingtimeController.create/2 (time_manager 0.1.0) lib/time_manager_web/controllers/workingtime_controller.ex:1: TimeManagerWeb.WorkingtimeController.action/2 (time_manager 0.1.0) lib/time_manager_web/controllers/workingtime_controller.ex:1: TimeManagerWeb.WorkingtimeController.phoenix_controller_pipeline/2
2

2 Answers

2
votes

Ecto.Changeset.cast/4 takes a schema struct as the first argument, not a schema module. In your create_workingtime/1 function, try changing to this:

%Workingtime{}
|> Workingtime.changeset(attrs)
|> Repo.insert()
0
votes

Found out the issue, in the create_workingtime function it was: %Workingtime{} isntead of just Workingtime

  def create_workingtime(attrs \\ %{}) do
    %{"start" => starttime, "end" => endtime, "user_id"=>user_id } = attrs
    {:ok, naivestart} = NaiveDateTime.from_iso8601(starttime)
    {:ok, naiveend} = NaiveDateTime.from_iso8601(endtime)
    attrs = %{"start" => naivestart, "end"=>naiveend, "user_id"=>user_id}
  
    %Workingtime{}
    |> Workingtime.changeset(attrs)
    |> Repo.insert()
  end