Ecto架构字段名称可以与列名称不同吗?

时间:2016-03-30 21:15:12

标签: elixir ecto

我有一个遗留数据库,我正试图进入Ecto。其中有一个orders表,其中包含order_status_id列。 order_status_id映射到遗留系统中的一组常量。

我希望MyApp.Order结构包含order_status字段,该字段具有将整数ID转换为有意义原子的自定义类型。我有自定义类型,但我无法弄清楚如何将名为order_status的字段映射到名为order_status_id的列。

旧系统仍在线并使用数据库,因此无法更改数据库架构。有没有办法让这个工作?

2 个答案:

答案 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名称。