Ecto adds plural ending to foreign key reference, causing runtime error

Running ecto 3.6.2 and in seeds.exs I’m simply updating every mediaitem with a timestamp and when ecto does the SELECT, it selects a non-existent column channels_id:

# set all seeded mediaitems to be publishable
FaithfulWord.Repo.all(from m in MediaItem)
|> Enum.map(fn mediaitem ->
  mediaitem
  |> change(published_at: DateTime.utc_now())
  |> Repo.update()
end)

error ("* (Postgrex.Error) ERROR 42703 (undefined_column) column m0.channels_id does not exist"):

[debug] QUERY ERROR source="mediaitems" db=0.0ms queue=10.1ms idle=14.9ms
SELECT m0."id", m0."comment", m0."description", m0."dislike_count", m0."size_bytes", m0."filepath", m0."height", m0."like_count", m0."tags", m0."title", m0."filename_hash", m0."upload_date", m0."artist", m0."view_count", m0."webpage_url", m0."width", m0."media_format", m0."skylink_id", m0."language_id", m0."localizedname", m0."ordinal", m0."cdn_path", m0."presenter_name", m0."presented_at", m0."source_material", m0."track_number", m0."media_category", m0."playlist_id", m0."org_id", m0."owner_id", m0."published_at", m0."readable_id", m0."duration", m0."channels_id", m0."playlists_id", m0."inserted_at", m0."updated_at" FROM "mediaitems" AS m0 []
** (Postgrex.Error) ERROR 42703 (undefined_column) column m0.channels_id does not exist

    query: SELECT m0."id", m0."comment", m0."description", m0."dislike_count", m0."size_bytes", m0."filepath", m0."height", m0."like_count", m0."tags", m0."title", m0."filename_hash", m0."upload_date", m0."artist", m0."view_count", m0."webpage_url", m0."width", m0."media_format", m0."skylink_id", m0."language_id", m0."localizedname", m0."ordinal", m0."cdn_path", m0."presenter_name", m0."presented_at", m0."source_material", m0."track_number", m0."media_category", m0."playlist_id", m0."org_id", m0."owner_id", m0."published_at", m0."readable_id", m0."duration", m0."channels_id", m0."playlists_id", m0."inserted_at", m0."updated_at" FROM "mediaitems" AS m0

    hint: Perhaps you meant to reference the column "m0.channel_id".
    (ecto_sql 3.6.2) lib/ecto/adapters/sql.ex:760: Ecto.Adapters.SQL.raise_sql_call_error/1
    (ecto_sql 3.6.2) lib/ecto/adapters/sql.ex:693: Ecto.Adapters.SQL.execute/5
    (ecto 3.6.2) lib/ecto/repo/queryable.ex:224: Ecto.Repo.Queryable.execute/4
    (ecto 3.6.2) lib/ecto/repo/queryable.ex:19: Ecto.Repo.Queryable.all/3
    priv/repo/seeds.exs:105: (file)
    (elixir 1.11.1) lib/code.ex:931: Code.require_file/2
    (mix 1.11.1) lib/mix/tasks/run.ex:146: Mix.Tasks.Run.run/5
    (mix 1.11.1) lib/mix/tasks/run.ex:86: Mix.Tasks.Run.run/1
    (mix 1.11.1) lib/mix/task.ex:394: Mix.Task.run_task/3
    (mix 1.11.1) lib/mix/cli.ex:84: Mix.CLI.run_task/2
    (elixir 1.11.1) lib/code.ex:931: Code.require_file/2

This was after I added a new column to MediaItem that I call channel_id:

defmodule FaithfulWord.Schema.MediaItem do
  use Ecto.Schema
  import Ecto.Changeset
...
  @primary_key {:id, :binary_id, autogenerate: true}
  @foreign_key_type :binary_id
  schema "mediaitems" do
...
    field :playlist_id, :binary_id
    field :channel_id, :binary_id
...
    belongs_to :channels, FaithfulWord.Schema.Channel
    belongs_to :playlists, FaithfulWord.Schema.Playlist

    timestamps(type: :utc_datetime_usec)
  end
...

migration:

defmodule FaithfulWord.Repo.Migrations.CreateMediaItems do
  use Ecto.Migration

  def change do
    create table(:mediaitems, primary_key: false) do
      add :id, :binary_id, primary_key: true
...
      add :org_id, references(:orgs, on_delete: :delete_all, type: :binary_id)
      add :owner_id, references(:users, on_delete: :delete_all, type: :binary_id)
      add :channel_id, references(:channels, on_delete: :delete_all, type: :binary_id)
      add :playlist_id, references(:playlists, on_delete: :delete_all, type: :binary_id)      timestamps(type: :utc_datetime_usec)
...
    end
...

Any idea ecto seems to add a pluralized version(“channels_id”) of the actual column(“channel_id”)? Is there a workaround?

Michael

1 Like

Isn’t it duplication?
When using belongs_to, it should not be necessary to define foreign_key fields

1 Like

Yes, I removed this line and it now uses channel_id. Thanks.

    belongs_to :channels, FaithfulWord.Schema.Channel