我有一个遗留数据库,我正试图进入Ecto。其中有一个orders
表,其中包含order_status_id
列。 order_status_id
映射到遗留系统中的一组常量。
我希望MyApp.Order
结构包含order_status
字段,该字段具有将整数ID转换为有意义原子的自定义类型。我有自定义类型,但我无法弄清楚如何将名为order_status
的字段映射到名为order_status_id
的列。
旧系统仍在线并使用数据库,因此无法更改数据库架构。有没有办法让这个工作?
答案 0 :(得分:3)
我不确定在第一次提出这个问题时是否可能,但现在有可能(Elixir 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”的列,但在Elixir应用程序内部,架构和变更集等将使用名为“foo”和“status”的属性
答案 1 :(得分: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
理论上,您还可以使用changeset函数执行相反的操作:根据order_status
设置order_status_id
,但会增加复杂性。
在我看来,最好的解决方案是简单地接受order_status_id
名称。