使 Ecto 模式字段名称不同于源表列名称 (Elixir)

Tom*_*ees 6 elixir ecto phoenix-framework

我目前正在从事一个 Phoenix 项目,我对在模板中调用字段的方式不满意。

该架构目前是

defmodule MyApp.Car do
  use MyApp.Web, :model
  schema "car" do
    field :columnName, :string
  end
end
Run Code Online (Sandbox Code Playgroud)

car = Repo.get!(Car, id)

我希望能够调用结果 car.column_name 而不是 car.columnName

由于许多应用程序使用数据库,因此迁移数据库目前不是一种选择。

zwi*_*pie 5

有一个source选项field

:source - 定义要在数据库中为此字段使用的名称。

defmodule MyApp.Car do
  use MyApp.Web, :model
  schema "car" do
    field :column_name, :string, source: :columnName
  end
end
Run Code Online (Sandbox Code Playgroud)


小智 0

如果您希望 Ecto 模式对引用驼峰命名法列的列名使用 Snake_case,则需要创建一个视图。如果您的视图只是用于重命名列,那么它在 Postgres/MySql/Microsoft SQL Server 中将是“可更新的”。这意味着INSERTUPDATEDELETE视图中的

例如,如果您的汽车表定义如下所示:

CREATE TABLE car(
   id             SERIAL PRIMARY KEY,
   modelName      VARCHAR(255),
   makeName       VARCHAR(255),
   manufacturerId INT REFERENCES manufacturer(id)
);
Run Code Online (Sandbox Code Playgroud)

您可以创建一个迁移,该迁移创建一个视图,从具有 Snake_case 别名的每一列中进行选择:

defmodule MyApp.Repo.Migrations.CarView do
  use Ecto.Migration

  def up do
    execute """
      CREATE VIEW my_app_car
      AS
      SELECT
          id AS id,
          modelName AS model_name,
          makeName AS make_name,
          manufacturerId AS manufacturer_id
      FROM car; 
    """
  end

  def down do
    execute "DROP VIEW my_app_car;"
  end
end
Run Code Online (Sandbox Code Playgroud)

并且您的 Ecto Schema 只需要使用您的视图作为其源(“my_app_car”而不是“car”):

defmodule MyApp.Car do
  use MyApp.Web, :model
  schema "my_app_car" do
    field :model_name, :string
    field :make_name, :string
    belongs_to :manufacturer, MyApp.Manufacturer
  end
end
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用MyApp.CarEcto 架构,就像其源是原始“car”表一样,但具有修改后的列名称。

如果您使用支持模式的数据库例如 Postgres、SQL Server),您可以为视图创建单独的模式,而不是将所有 ecto 视图命名为“my_app_[TABLE NAME]”。