AJP
AJP

Reputation: 545

Elixir- Cannot save Ecto.DateTime into Postgres database, where saving Ecto.Date works

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?

Upvotes: 1

Views: 1072

Answers (1)

Dogbert
Dogbert

Reputation: 222040

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

Upvotes: 3

Related Questions