Ecto Schema Issue - Can't make an association between two tables?

I am trying to make an association between tables however I am getting hit with an error.

I currently have a “users” table with the following fields:

id email password first_name last_name role
1 hash Bob White teacher
2 hash Joe Brown student

I am trying to implement two new user types: teachers and students

As such, I want to make two different tables for both user types which will reference the main table like so:

  • teachers table
id user_id first_name last_name
1 1 (reference to “users”) Bob White
  • students table
id user_id first_name last_name
1 2 (reference to “users”) Joe Brown

I generated a new migration and created the “teachers” table like so:

create table("teachers") do
   add :user_id, references("users")
   add :first_name, :string
   add :last_name, :string

I then defined a schema for the teachers table like this:

schema "teachers" do
   field :user_id, :integer
   field :first_name, :string
   field :last_name, :string

   belongs_to :user, User

Lastly, I added this to the user schema:

   has_many :teachers, Teacher

After running mix ecto.migrate the teachers table was created, but I am getting this compilation error:

== Compilation error in file lib/task_app/teachers/teacher.ex ==
** (ArgumentError) field/association :user_id is already set on schema
    (ecto 3.7.1) lib/ecto/schema.ex:2137: Ecto.Schema.put_struct_field/3
    (ecto 3.7.1) lib/ecto/schema.ex:1890: Ecto.Schema.define_field/4
    (ecto 3.7.1) lib/ecto/schema.ex:1977: Ecto.Schema.__belongs_to__/4
    lib/task_app/teachers/teacher.ex:11: (module)

I don’t know where I went wrong with the setup. But I would appreciate advice on how I can make this association.

What is on line 11 of teacher.ex? My guess is that’s the belongs_to :user, User line.

belongs_to takes care of declaring the field it uses, so having the previous declaration of field :user_id, :integer causes the error you’re seeing.

1 Like

It is the belongs_to line in the teacher schema:

belongs_to :user, User

So you are correct.

Removing field :user_id, :integer fixed the compilation error, I will see if the association works as intended :slight_smile:

Thank you

You’re also able to keep both the field and belongs_to definitions, for example in the case that you need to use field-specific options that are not available on the relationship, by setting define_field: false.

belongs_to/3 Options

  • :define_field - When false, does not automatically define a :foreign_key field, implying the user is defining the field manually elsewhere
1 Like