2017-01-31 1 views
1

나는 모든 모델에서 timestamps을 사용하는 phoenix 앱을 가지고 있습니다. 자동으로 이러한 필드를 생성하는 (새로운 또는 생성)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 매크로 메이크업 그렇게 모든 방법을 사용할 수있다.

1 : 당신은 두 가지 옵션이 있습니다 https://gist.github.com/pavlos/c86858290743b4d4fed9

답변

0

다음 Extension 모듈은 여기에서 유래합니다. timestamps에서 Ecto.Schema까지 확장하고 timestamps 함수에서 Ecto.Migration의 함수를 모델 및 마이그레이션에서 가져올 것을 고려하십시오. 열을 소스 코드에서 구현 한 것과 같은 방법으로 구현하십시오.

이 접근 수도 :

  • 때문에
  • 때문에
  • 구현하고 승리하도록 어려울 소스 코드의 더 나은 지식을 더 도움이 될 소스 코드를 파고 공부의 시간이 더 소요 실수하지 마라.

. timestamps의 기능을 확장하는 대신 도우미의 새로운 함수 또는 매크로를 사용하십시오. 그것은됩니다

  • 쉽게

당신이 당신의 모델,하지만 의미 데이터베이스에서뿐만 아니라 이러한 필드를 갖고 싶어 그 기억 구현할 수 적은 시간과 노력

  • 소요 마이그레이션에 추가하거나 데이터베이스의 현재 값을 기반으로 추가 할 스크립트를 준비해야합니다.

  • +0

    스키마 및 마이 그 레이션을 제안대로 확장하려고 시도했지만 이제는 업데이트에서 언급 한 다른 문제가 발생합니다. 이견있는 사람? – user2694306

    +0

    확장 아이디어를 버리십시오. 2. 접근 방식을 사용하면 더 빠르고 더 안전 할 것이며 아무 것도 깨뜨리지 않을 것입니다. – PatNowak

    관련 문제