2016-03-30 5 views
1

Ich habe eine Legacy-Datenbank, die ich versuche, in Ecto zu ziehen. Darin gibt es eine orders Tabelle, die eine order_status_id Spalte hat. order_status_id bildet eine Menge von Konstanten im Altsystem ab.Kann sich der Ecto-Schema-Feldname vom Spaltennamen unterscheiden?

Ich möchte die MyApp.Order Struktur enthalten ein order_status Feld, das einen benutzerdefinierten Typ hat, der die Ganzzahl-IDs in sinnvolle Atome konvertiert. Ich habe den benutzerdefinierten Typ funktioniert, aber ich kann nicht herausfinden, wie ein Feld mit dem Namen order_status zu einer Spalte mit dem Namen order_status_id zugeordnet wird.

Das Legacy-System ist noch online und verwendet die Datenbank, daher ist das Ändern des DB-Schemas keine Option. Gibt es eine Möglichkeit, dies zum Laufen zu bringen?

Antwort

1

Ich denke, es ist derzeit nicht möglich, Modellfeld einfach mit anderen Spaltennamen zu verknüpfen. Wenn Sie den Namen order_status wirklich verwenden möchten, können Sie zusätzlich virtual field erstellen. Diese Felder werden nicht in der Datenbank gespeichert. Dann sollte Ihre cast Funktion für die Änderung order_status_id basierend auf Params verantwortlich sein.

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 

Theoretisch können Sie auch Funktion changeset die entgegengesetzte Operation zu tun: set order_status basierend auf order_status_id, aber es erhöht die Komplexität.

Meiner Meinung nach wäre die beste Lösung, einfach order_status_id Namen zu akzeptieren.

+0

Mein Verständnis ist, dass 'changeset \ 2' nur ausgeführt wird, wenn ein Datensatz erstellt oder persistiert wird. Ich glaube nicht, dass diese Lösung das Feld 'order_status' beim Laden eines Datensatzes aus der Datenbank füllen würde. –

+0

Das stimmt, aber schauen Sie sich alle Codebeispiele selbst von Generatoren an. Sie sollten immer Änderungssets verwenden, bevor Sie auf die Datenbank zugreifen. Beim Schreiben darauf bieten Changesets eine Validierung für alle Dinge, die nicht auf db zugreifen müssen, und einfache Fehlermeldungen für Datenbankeinschränkungen. Wenn Sie aus der Datenbank lesen, sollten Sie auch changeset verwenden: 'model = Repo.get (Model, id) changeset = Model.changeset (model)' – tkowal

1

Ich bin mir nicht sicher, ob es möglich war, als die Frage zuerst gestellt wurde, aber es ist jetzt möglich (Elixir 1.5). Siehe https://hexdocs.pm/ecto/Ecto.Schema.html Insbesondere die Optionen @field_source_mapper und :source. Die :source Option ist recht einfach - sind es nur in Ihrem schema Definition etwas wie folgt aus:

schema "orders" do 

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

    end 

Im obigen Beispiel wird die vorhandene Datenbanktabelle hat Spalten mit den Namen „legacy_foo_db_column“ und „order_status“, aber intern in der Die Elixir-App, das Schema und der Änderungssatz usw. verwenden die Attribute "foo" und "status"

Verwandte Themen