1

In a Phoenix app, I would like to save a session record to a Postgres DB, with the expires field being 12 hours from now. My session model sets the expires field as an Ecto.DateTime.

Model

schema "sessions" do
    field :key, :string
    field :expires, Ecto.DateTime
    field :user_id, :integer

    timestamps()
  end

When authentication succeeds in the login controller, I construct the session object and send it to the create function in the session controller. Timex is used to determine the time 12 hours from now.

Login Controller

{:ok, session_expiry} = Ecto.DateTime.cast(Timex.to_datetime(Timex.shift(Timex.now, hours: 12)))
# Returns {:ok, #Ecto.DateTime<2017-07-13 20:56:25.969059>}
    session_object = %{
      "key" => encrypted_auth_code,
      "expires" => session_expiry,
      "user_id" => user_id
    }
    SessionController.create(%{"data" => data = %{"type" => "session", "attributes" => session_object}})

Session controller

def create(%{"data" => data = %{"type" => "session", "attributes" => _session_params}}) do
    changeset = Session.changeset(%Session{}, Params.to_attributes(data))
    IO.inspect _session_params
    case Repo.insert(changeset) do
      {:ok, session} ->
        IO.puts "success"
      {:error, changeset} ->
        IO.puts "failure"
    end
  end

In the session controller the line case Repo.insert(changeset) do throws the following error:

no function clause matching in Ecto.Adapters.Postgres.DateTime.encode_date/1

If I change the type of the expires field in the session model to Ecto.Date the database record is created successfully, but without the time.

What do I need to change in order to save to an Ecto.DateTime field to the DB?

2
  • 1
    What is the type of expires column in your database (or migration)? Maybe you used the date type instead of datetime in the migration? Commented Jul 13, 2017 at 9:13
  • I did! Thank you. Changed the expires field to type timestamp and it works perfectly now. Commented Jul 13, 2017 at 9:22

1 Answer 1

3

If Ecto.Date works the type of the field in your database is probably date instead of utc_datetime (timestamp in PostgreSQL). Changing it to utc_datetime should fix the error. If you used migrations to create the table, you can create a new one which alters the type of the column like this:

def up do
  alter table(:sessions) do
    modify :expires, :utc_datetime
  end
end

def down do
  alter table(:sessions) do
    modify :expires, :date # old type here
  end
end
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.