使Ecto架构字段名称与源表列名称(Elixir)不同

问题描述 投票:3回答:3

我目前正在开发凤凰项目,我对模板中的字段调用方式不满意。

架构是目前的

defmodule MyApp.Car do
  use MyApp.Web, :model
  schema "car" do
    field :columnName, :string
  end
end

car = Repo.get!(Car, id)

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

由于许多应用程序使用数据库,因此目前无法迁移数据库。

elixir phoenix-framework ecto
3个回答
1
投票

我相信这可以做到Ecto的field source mapper

defmodule MyApp.Car do
  use Ecto.Schema

  @field_source_mapper fn
    :column_name -> :columnName
    x -> x
  end

  schema "car" do
    field :column_name, :string
  end
end

0
投票

如果希望Ecto架构对引用camelCase列的列名使用snake_case,则需要创建一个视图。如果您的视图仅用于重命名列,则它将在Postgres / MySql / Microsoft SQL Server中为“updatable”。这意味着INSERTUPDATEDELETE进入视图将写入视图引用的实际表。

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

CREATE TABLE car(
   id             SERIAL PRIMARY KEY,
   modelName      VARCHAR(255),
   makeName       VARCHAR(255),
   manufacturerId INT REFERENCES manufacturer(id)
);

您可以创建一个迁移,创建一个视图,从每个列中选择一个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

并且您的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

然后,您可以使用MyApp.Car Ecto架构,就好像它的源是原始的“car”表,但是使用修改后的列名。

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


0
投票

有一个source option for field

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

defmodule MyApp.Car do
  use MyApp.Web, :model
  schema "car" do
    field :column_name, :string, source: :columnName
  end
end
© www.soinside.com 2019 - 2024. All rights reserved.