问题
I've got a legacy database that I'm trying to pull into Ecto. In it there's an orders
table which has an order_status_id
column. order_status_id
maps to a set of constants in the legacy system.
I'd like to have the MyApp.Order
struct contain an order_status
field, which has a custom type that converts the integer IDs to meaningful atoms. I've got the custom type working, but I can't figure out how to map a field named order_status
to a column named order_status_id
.
The legacy system is still online and using the database, so changing the DB schema is not an option. Is there any way to get this working?
回答1:
I'm not sure if it was possible when the question was first asked, but it is possible now (Elixir 1.5). See https://hexdocs.pm/ecto/Ecto.Schema.html
In particular the @field_source_mapper
and :source
options. The :source
option is pretty easy -- just include it in your schema
definition something like this:
schema "orders" do
field :foo, :string, [source: :legacy_foo_db_column]
field :status, :integer, [source: :order_status]
end
In the above example, the existing database table has columns named "legacy_foo_db_column" and "order_status", but internally in the Elixir app, the schema and changeset etc. will use attributes named "foo" and "status"
回答2:
I think, it is currently not possible to simply associate model field with different column name.
If you really want to use name order_status
, you can create additional virtual field. Those fields are not persisted to database. Then your cast
function should be responsible for changing order_status_id
based on params.
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
In theory, you can also use changeset function to do the opposite operation: set order_status
based on order_status_id
, but it adds complexity.
In my opinion, the best solution would be to simply accept order_status_id
name.
来源:https://stackoverflow.com/questions/36319893/can-the-ecto-schema-field-name-different-from-column-name