2016-09-10 1 views
1

私はフィールドの1つを%Cm{value: 1.0}(センチメートル単位)の形で表現したいと思うスキーマを持っています。 DBタイプの名前が Ectoカスタムタイプ:モデル内のフィールドを特定のタイプとして表現するにはどうすればよいですか?

  • cast出力がすべき

    • type必要があります:ドキュメント(https://hexdocs.pm/ecto/Ecto.Type.html)から、これらのガイドラインに続いて

      defmodule Db.Types.Cm do 
          alias Units.Cm 
      
          @behavior Ecto.Type 
          def type, do: :float 
      
          def cast(%Cm{value: integer}) when is_integer(integer) do 
          Cm.new(integer/1.0) 
          end 
      
          def cast(val = %Cm{value: float}) when is_float(float) do 
          val 
          end 
      
          def cast(number) when is_float(number), do: Cm.new(number) 
          def cast(number) when is_integer(number), do: Cm.new(number/1.0) 
          def cast(_), do: :error 
      
          def load(float) when is_float(float), do: Cm.new(float) 
      
          def dump(%Cm{value: float}) when is_float(float), do: float 
          def dump(%Cm{value: integer}) when is_integer(integer), do: (integer/1.0) 
          def dump(_), do: :error 
      end 
      

      :私はこの、カスタマーのタイプを定義している

      任意のタイプを受け取り、カスタムEctoタイプを出力する

    • loadカスタムエクトタイプと出力DBタイプ

    そして、次のスキーマ受けるべきDBのタイプと出力カスタムエクトタイプ

  • dumpを受ける必要があります。今

    defmodule Db.Block do 
        schema "blocks" do 
        field :max_depth, Types.Cm 
        timestamps() 
        end 
    
        @fields ~w(max_depth)a 
    
        def changeset(struct, params \\ %{}) do 
        struct 
        |> cast(params, @fields) 
        end 
    end 
    

    をI dbにブロックを保存しようとする:

    defmodule Db.BlockHelpers do 
        def new_block(attributes \\ %{}) do 
        block = Dict.merge(%{ 
         max_depth: 2 
        }, attributes) 
    
        %Block{} 
        |> Block.changeset(block) 
        |> Repo.insert! 
        end 
    end 
    
    iex> new_block() 
    ...> new_block(%{max_depth: Units.Cm.new(5.0)}) 
    

    しかし、私はエラーを得続ける:

    ** (CaseClauseError) no case clause matching: %Units.Cm{value: 2.0} 
    

    私はアプローチの様々な組み合わせを試してみたが、それは右のように見えることはできません。だから私は100%私はドキュメントを理解しているわけではない。

    今日の終わりに、%Block{max_depth: %Units.Cm{value: 1.0}}という形式のモデル構造体を渡すことができるようになりました。ここでcm値はデータベース(postgres)の浮動小数点として格納されています。

  • +1

    'Db.Typesのすべての成功事例から' {cm: 'が'%Cm {...} 'や' Cm.new(...) 'を返すようにしてください。 .Cm.cast/1'。 – Dogbert

    答えて

    0

    正解Dogbert:{:ok, value}ではなくvalueが返されました。

    関連する問題