私はすべてのモデルでtimestamps
を利用するphoenix appを持っています。Elixir Phoenix - タイムスタンプに列を追加
created_at (utc datetime)
updated_at (utc datetime)
created_at_utc (utc timestamp of created_at field)
updated_at_utc (utc timestamp of updated_at field)
どのように私は、タイムスタンプ機能を拡張(または新しいものを生成する)ことができ、自動的にこれらのフィールドを生成する:しかし、私は私がモデルにtimestamps
を含めいつでも、それは次のフィールドが追加されるようにタイムスタンプを拡張したいですか?
UPDATE 私は下図のように私のヘルパーdb_helpers.ex
にEcto.SchemaとEcto.Migrationsモジュールを拡張しようとしてきた答えで示唆したように:
defmodule Extension do
defmacro extends(module) do
module = Macro.expand(module, __CALLER__)
functions = module.__info__(:functions)
signatures = Enum.map functions, fn { name, arity } ->
args = Enum.map 0..arity, fn(i) ->
{ String.to_atom(<< ?x, ?A + i >>), [], nil }
end
{ name, [], tl(args) }
end
quote do
defdelegate unquote(signatures), to: unquote(module)
defoverridable unquote(functions)
end
end
end
defmodule Ecto.Schema do
import Extension
extends Ecto.Schema
@doc """
Generates `:inserted_at` and `:updated_at` timestamp fields.
The fields generated by this macro will automatically be set to
the current time when inserting and updating values in a repository.
## Options
* `:type` - the timestamps type, defaults to `:naive_datetime`.
* `:type_utc` - the utc timestamps type, defaults to `:utc_datetime`.
* `:usec` - sets whether microseconds are used in timestamps.
Microseconds will be 0 if false. Defaults to true.
* `:created_at` - the name of the column for insertion times or `false`
* `:updated_at` - the name of the column for update times or `false`
* `:created_at_utc` - the name of the column for utc insertion times or `false`
* `:updated_at_utc` - the name of the column for utc update times or `false`
* `:autogenerate` - a module-function-args tuple used for generating
both `inserted_at` and `updated_at` timestamps
All options can be pre-configured by setting `@timestamps_opts`.
"""
defmacro timestamps(opts \\ []) do
quote bind_quoted: binding() do
timestamps =
[created_at: :created_at, updated_at: :updated_at,
created_at_utc: :created_at_utc, inserted_at_utc: :inserted_at_utc,
type: :naive_datetime, type_utc: :utc_datetime,
usec: true]
|> Keyword.merge(@timestamps_opts)
|> Keyword.merge(opts)
type = Keyword.fetch!(timestamps, :type)
type_utc = Keyword.fetch!(timestamps, :type_utc)
precision = if Keyword.fetch!(timestamps, :usec), do: :microseconds, else: :seconds
autogen = timestamps[:autogenerate] || {Ecto.Schema, :__timestamps__, [type, precision]}
if created_at = Keyword.fetch!(timestamps, :created_at) do
Ecto.Schema.field(created_at, type, [])
Module.put_attribute(__MODULE__, :ecto_autogenerate, {created_at, autogen})
end
if updated_at = Keyword.fetch!(timestamps, :updated_at) do
Ecto.Schema.field(updated_at, type, [])
Module.put_attribute(__MODULE__, :ecto_autogenerate, {updated_at, autogen})
Module.put_attribute(__MODULE__, :ecto_autoupdate, {updated_at, autogen})
end
if created_at_utc = Keyword.fetch!(timestamps, :created_at_utc) do
Ecto.Schema.field(created_at_utc, type, [])
Module.put_attribute(__MODULE__, :ecto_autogenerate, {created_at_utc, autogen})
end
if updated_at_utc = Keyword.fetch!(timestamps, :updated_at_utc) do
Ecto.Schema.field(updated_at_utc, type, [])
Module.put_attribute(__MODULE__, :ecto_autogenerate, {updated_at_utc, autogen})
Module.put_attribute(__MODULE__, :ecto_autoupdate, {updated_at_utc, autogen})
end
end
end
end
defmodule Ecto.Migration do
import Extension
extends Ecto.Migration
@doc """
Adds `:created_at` and `:updated_at` timestamps columns.
Those columns are of `:naive_datetime` type, and by default
cannot be null. `opts` can be given to customize the generated
fields.
## Options
* `:created_at` - the name of the column for insertion times, providing `false` disables column
* `:updated_at` - the name of the column for update times, providing `false` disables column
* `:created_at_utc` - the name of the column for utc insertion times, providing `false` disables column
* `:updated_at_utc` - the name of the column for utc update times, providing `false` disables column
* `:type` - column type, defaults to `:naive_datetime`
* `:type_utc` - column type for utc, defaults to `:utc_datetime`
"""
def timestamps(opts \\ []) do
opts = Keyword.put_new(opts, :null, false)
{type, opts} = Keyword.pop(opts, :type, :naive_datetime)
{type_utc, opts} = Keyword.pop(opts, :type_utc, :utc_datetime)
{created_at, opts} = Keyword.pop(opts, :created_at, :created_at)
{updated_at, opts} = Keyword.pop(opts, :updated_at, :updated_at)
{created_at_utc, opts} = Keyword.pop(opts, :created_at_utc, :created_at_utc)
{updated_at_utc, opts} = Keyword.pop(opts, :updated_at_utc, :updated_at_utc)
if created_at != false, do: add(created_at, type, opts)
if updated_at != false, do: add(updated_at, type, opts)
if created_at_utc != false, do: add(created_at_utc, type_utc, opts)
if updated_at_utc != false, do: add(updated_at_utc, type_utc, opts)
end
end
しかし、私が実行しようとしますmix ecto.migrate
私は、次のエラーを取得しています:すべてのメソッドが利用できるように
== Compilation error on file web/models/accounts.ex ==
** (CompileError) web/models/accounts.ex:4: undefined function schema/2
(stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
(elixir) lib/kernel/parallel_compiler.ex:117: anonymous fn/4 in Kernel.ParallelCompiler.spawn_compilers/1
マクロextends
はそれを行うべきではありません。
:あなたは2つのオプションがありhttps://gist.github.com/pavlos/c86858290743b4d4fed9
私はスキーマと移行を提案するように拡張しようとしましたが、今回のアップデートで言及されている他の問題が発生しています。何かご意見は? – user2694306
延長のアイデアを落とす:) 2.アプローチを使用すると、何かを壊さないように、より速く、より安全になります。 – PatNowak