Default datetime with Ecto & Elixir

2019-04-25 12:15发布

问题:

I've just started working Elixir & Phoenix today, i am trying to add Ecto as a mapper, but i'm having some trouble using time.

This is my model.

  schema "users" do
    field :name, :string
    field :email, :string
    field :created_at, :datetime, default: Ecto.DateTime.local
    field :updated_at, :datetime, default: Ecto.DateTime.local
  end

I'm trying to set the created_at and updated_at per default, but when i try to compile this, i get the following error.

== Compilation error on file web/models/user.ex ==
** (ArgumentError) invalid default argument `%Ecto.DateTime{day: 13, hour: 19, min: 47, month: 2, sec: 12, year: 2015}` for `:datetime`
lib/ecto/schema.ex:687: Ecto.Schema.check_default!/2
lib/ecto/schema.ex:522: Ecto.Schema.__field__/4
web/models/board.ex:9: (module)
(stdlib) erl_eval.erl:657: :erl_eval.do_apply/6

There is not much help to get in the documentation, what would be the correct way to do this?

回答1:

:datetime is the native Postgres data type for, well a datetime; this data type maps to a two-elements Elixir tuple ({{yy, mm, dd}, {hh, mm, ss}}). An %Ecto.DateTime{} struct is not a two-elements tuple, hence the compilation error.

You may want to set the type of your fields to Ecto.DateTime, it should all work seamlessly.

Here is the relevant documentation about primitive types and non-primitive types.

PS you may also want to have a look at Ecto.Schema.timestamps/1, which is macro that expands to basically what you wrote manually (it adds the created_at and updated_at fields and it let's you choose what type they should be, defaulting to Ecto.DateTime):

schema "users" do
  field :name, :string
  field :email, :string
  timestamps
end


回答2:

Defaults fields names are :inserted_at and :updated_at but you can merge with your own field names, passing a keyword list

schema "users" do
  field :name, :string
  field :email, :string
  timestamps([{:inserted_at,:created_at}])
end


回答3:

You could also consider having the default not be in the schema, but in the migration: "created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP"