Unable to preload in Phoenix 1.3

I’ve generated two resources:

  1. $ mix phx.gen.json Accounts User users name:string email:string ...
  2. $ mix phx.gen.json Forums Post posts title:string content:text accounts_users_id:references:accounts_users

Modified my schemas as follows:

schema "forums_posts" do
    field :content, :string
    field :title, :string
    # If I leave this uncommented it will not even compile
    # field :accounts_users_id, :id
    
    belongs_to :accounts_users, MyApp.Accounts.User

    timestamps()
  end
  schema "accounts_users" do
    field :email, :string
    field :encrypted_password, :string
    field :name, :string
    field :username, :string
    
    has_many :forums_posts, MyApp.Forums.Post

    timestamps()
  end

Generated migrations:

  def change do
    create table(:accounts_users) do
      add :username, :string, null: false
      add :email, :string, null: false
      add :name, :string, null: false
      add :encrypted_password, :string

      timestamps()
    end

    create unique_index(:accounts_users, [:username])
    create unique_index(:accounts_users, [:email])
end

def change do
    create table(:forums_posts) do
      add :title, :string, null: false
      add :content, :text, null: false
      add :accounts_users_id, references(:accounts_users, on_delete: :nothing)

      timestamps()
    end

    create index(:forums_posts, [:accounts_users_id])
end

However, I am not able to preload data, i.e.

iex(4)> Repo.get(User, 1) |> Repo.preload(:forums_posts) 
[debug] QUERY OK source="accounts_users" db=1.4ms
SELECT a0."id", a0."email", a0."encrypted_password", a0."name", a0."username", a0."inserted_at", a0."updated_at" FROM "accounts_users" AS a0 WHERE (a0."id" = $1) [1]
** (Ecto.QueryError) deps/ecto/lib/ecto/association.ex:495: field `MyApp.Forums.Post.user_id` in `where` does not exist in the schema in query:

from p in MyApp.Forums.Post,
  where: p.user_id == ^1,
  order_by: [asc: p.user_id],
  select: {p.user_id, p}

Why is it looking up for user_id in first place?

Thank you for your time.

1 Like

try:
belongs_to :accounts_users, MyApp.Accounts.User, foreign_key: :accounts_users_id

1 Like

The error persists:

  schema "forums_posts" do
    field :content, :string
    field :title, :string
    
    belongs_to :accounts_users, MyApp.Accounts.User, foreign_key: :accounts_users_id

    timestamps()
  end
iex(4)> Repo.get(User, 1) |> Repo.preload(:forums_posts)
[debug] QUERY OK source="accounts_users" db=1.3ms
SELECT a0."id", a0."email", a0."encrypted_password", a0."name", a0."username", a0."inserted_at", a0."updated_at" FROM "accounts_users" AS a0 WHERE (a0."id" = $1) [1]
** (Ecto.QueryError) deps/ecto/lib/ecto/association.ex:495: field `MyApp.Forums.Post.user_id` in `where` does not exist in the schema in query:

from p in MyApp.Forums.Post,
  where: p.user_id == ^1,
  order_by: [asc: p.user_id],
  select: {p.user_id, p}
1 Like

the foreign key should be set on has_many:

 has_many :forums_posts, MyApp.Forums.Post, foreign_key: :accounts_users_id

However it seems to be a bug.

Update

It’s not a bug, Ecto uses only last part of your module name to build default foreign key by design. reference in Ecto codebase