2016-03-30 9 views
1

私はEctoに取り込もうとしているレガシーデータベースを持っています。その中にorder_status_idの列を持つordersテーブルがあります。 order_status_idは、レガシーシステムの一連の定数にマップされます。Ectoスキーマのフィールド名を列名と異なることはできますか?

MyApp.Order構造体にorder_statusフィールドが含まれていて、整数型IDを意味のあるアトムに変換するカスタムタイプがあります。私はカスタム型を動作させていますが、order_statusという名前のフィールドを、order_status_idという名前のカラムにどのようにマップするのか分かりません。

レガシーシステムは、オンラインので、DBスキーマを変更し、データベースを使用して、まだ選択肢はないです。これを実現する方法はありますか?

答えて

1

私はそれが別の列名を指定して、単純に関連付けるモデルフィールドに現在可能ではない、と思います。

あなたが本当に名前order_statusを使用したい場合は、追加のvirtual fieldを作成することができます。これらのフィールドはデータベースに保持されません。その後、cast関数は、パラメータに基づいてorder_status_idを変更する責任があります。理論的には

def changeset(model, params \\ :empty) do 
    model 
    |> cast(params, @required_fields, @optional_fields) 
    |> put_order_status_id 
end 

defp put_order_status_id(changeset) do 
    case changeset do 
    %Ecto.Changeset{valid?: true, changes: %{order_status: status}} -> 
     put_change(changeset, :order_status_id, id_from_status(status)) 
    _ -> 
     changeset 
    end 
end 

、あなたはまた、逆の操作を行うにはチェンジ機能を使用することができます。order_status_idに基づいてorder_statusを設定するが、それは複雑になります。私の意見で

、最善の解決策は、単にorder_status_id名前を受け入れることであろう。

+0

私の理解では、 '2' \チェンジがレコードを作成または永続化するときにのみ実行されるということです。データベースからレコードをロードするときに、この解決策が 'order_status'フィールドに移入するとは思いません。 –

+0

それは本当ですが、ジェネレータからのコード例もすべて見てください。データベースにアクセスする前に、常にチェンジセットを使用する必要があります。これに書き込むとき、チェンジセットはdbにアクセスする必要のないすべてのものと、データベース制約のためのフレンドリなエラーメッセージの検証を提供します。データベースから読み込むときには、チェンジセットも使うべきです: 'model = Repo.get(Model、id)changeset = Model.changeset(model)' – tkowal

1

(エリクサー1.5)私は質問が最初に尋ねられたとき、それが可能だったかどうかわからないんだけど、それが可能になりました。 https://hexdocs.pm/ecto/Ecto.Schema.html 特に@field_source_mapperおよび:sourceのオプションを参照してください。 :sourceオプションは非常に簡単です - ちょうどあなたのschema定義でこのようなもの、それが含まれています。上記の例で

schema "orders" do 

    field :foo, :string, [source: :legacy_foo_db_column] 
    field :status, :integer, [source: :order_status] 

    end 

を、既存のデータベース・テーブルには、「legacy_foo_db_column」と「ORDER_STATUS」という名前の列がありますが、内部的にエリクサーアプリ、スキーマとチェンジなど「foo」という名前の属性を使用し、「状態」になる

関連する問題