2017-04-20 15 views
3

私のエクトモデルでは、user_timestampをunix_timeから変換したフィールドを指定する必要があります。 移行:elixir ecto naive_datetimeキャストエラー

def change do 
    alter table(:operations) do 
     add :user_timestamp, :naive_datetime, null: false 
    end 
    end 

私operation.ex

schema "operations" do 
    field :sum, :float 
    field :name, :string 
    field :user_timestamp, :naive_datetime 

    timestamps() 
    end 

    def changeset(struct, params \\ %{}) do 
    struct 
    |> cast(params, [:name, :sum, :user_timestamp]) 
    |> validate_required([:sum, :user_timestamp]) 
    |> convert_unix_time_to_ecto 
    end 

    defp convert_unix_time_to_ecto(changeset) do 
    put_change(changeset, :user_timestamp, Ecto.DateTime.from_unix!(changeset.changes.user_timestamp, :seconds) |> Ecto.DateTime.to_naive()) 
    end 

しかし、私はuser_timestampを持つの要件を追加しようとすると、私はエラーを取得:

[error] #PID<0.492.0> running MyApp.Endpoint terminated 
Server: localhost:4000 (http) 
Request: POST /api/v1/operations 
** (exit) an exception was raised: 
    ** (FunctionClauseError) no function clause matching in Ecto.Type.cast_naive_datetime/1 
     (ecto) lib/ecto/type.ex:761: Ecto.Type.cast_naive_datetime(1492722276) 
     (ecto) lib/ecto/changeset.ex:523: Ecto.Changeset.cast_field/8 
     (ecto) lib/ecto/changeset.ex:482: Ecto.Changeset.process_param/8 
     (elixir) lib/enum.ex:1325: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3 
     (elixir) lib/enum.ex:1325: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3 
     (ecto) lib/ecto/changeset.ex:450: Ecto.Changeset.do_cast/7 
     (my_app) web/models/operation.ex:25: MyApp.Operation.changeset/2 
     (my_app) web/models/operation.ex:32: MyApp.Operation.create_changeset/2 
     (my_app) web/controllers/v1/operation_controller.ex:25: MyApp.V1.OperationController.create/2 
     (my_app) web/controllers/v1/operation_controller.ex:1: MyApp.V1.OperationController.action/2 
     (my_app) web/controllers/v1/operation_controller.ex:1: MyApp.V1.OperationController.phoenix_controller_pipeline/2 
     (my_app) lib/my_app/endpoint.ex:1: MyApp.Endpoint.instrument/4 
     (my_app) lib/phoenix/router.ex:261: MyApp.Router.dispatch/2 
     (my_app) web/router.ex:1: MyApp.Router.do_call/2 
     (my_app) lib/my_app/endpoint.ex:1: MyApp.Endpoint.phoenix_pipeline/1 
     (my_app) lib/plug/debugger.ex:123: MyApp.Endpoint."call (overridable 3)"/2 
     (my_app) lib/my_app/endpoint.ex:1: MyApp.Endpoint.call/2 
     (plug) lib/plug/adapters/cowboy/handler.ex:15: Plug.Adapters.Cowboy.Handler.upgrade/4 
     (cowboy) /home/mars/phoenix_projects/my_app/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4 

がどのように修正することができますがこのエラー?

答えて

3

変換コードが実行されるまでには、castに失敗しています。

キャストフィールドリストの外に:user_timestampを置き換え、validate_requiredの前に変換された値を持つput_changeを使用します。

def changeset(struct, params \\ %{}) do 

    struct 
    |> cast(params, [:name, :sum]) 
    |> convert_unix_time_to_ecto(params["user_timestamp"]) 
    |> validate_required([:sum, :user_timestamp]) 

    end 

    defp convert_unix_time_to_ecto(changeset, nil), do: changeset  
    defp convert_unix_time_to_ecto(changeset, timestamp) do 
    datetime = 
     timestamp 
     |> DateTime.from_unix!(:seconds) 
     |> DateTime.to_naive() 

    put_change(changeset, :user_timestamp, datetime) 
    end 
関連する問題