Ecto (Phoenix) 中的外键数组

Array of foreign keys in Ecto (Phoenix)

我是网络开发的初学者,请原谅我的知识不足。

我有一个 Teacher 和一个 Student Ecto 架构。它们应该按照以下规则通过另一个名为 Class 的模式链接:

  1. 每个class只有一个老师,并且有一组学生。

  2. 每个老师都可以成为许多 classes

  3. 的一部分
  4. 每个学生都可以成为许多 classes 的一部分。

这是我到目前为止构建的架构:

# Part of student.ex
schema "students" do
    field :active, :boolean, default: false
    field :birthday, :date
    field :email, :string, unique: true
    field :firstname, :string
    field :lastname, :string
    field :phone, :string, unique: true
    belongs_to :classes, Class, foreign_key: :class_id
    many_to_many :teachers, Users.Teacher, join_through: "classes"

    timestamps()
  end
# Part of teacher.ex
schema "teachers" do
    field :active, :boolean, default: false
    field :birthday, :date
    field :email, :string, unique: true
    field :firstname, :string
    field :lastname, :string
    field :phone, :string, unique: true
    belongs_to :classes, Class, foreign_key: :class_id
    many_to_many :students, Users.Student, join_through: "classes"
    timestamps()
  end
# Part of class.ex
schema "classes" do
    field :end_date, :date
    field :time, :time
    field :level, :string
    field :start_date, :date
    field :title, :string
    has_many :students, Users.Student
    has_one :teacher, Users.Teacher
    embeds_many :sessions, Session
    timestamps()
  end

这里看起来一切正常。但问题是,如何在迁移文件中指定 "an array of student ids" ?以下是迁移函数:

# Part of students migration file. It's the same for teachers.
def change do
    create table(:students) do
      add :firstname, :string, null: false, size: 32
      add :lastname, :string, null: false, size: 32
      add :phone, :string, null: false, size: 16
      add :email, :string, size: 32
      add :birthday, :date
      add :active, :boolean, default: false, null: false

      timestamps()
    end

    create(unique_index(:students, [:phone]))
  end

这就是我现在真正陷入困境的地方:

def change do
    create table(:classes) do
      add :title, :string, null: false
      add :level, :string
      add :hours, :string, null: false
      add :start_date, :date
      add :end_date, :date
      add :teacher_id, references(:teachers), primary_key: true
      # HERE! How do I create a column for an array of student_id foreign keys?
      timestamps()
    end

    create(index(:classes, [:teacher_id]))

  end

提前致谢。

正如 Ecto.Schema.belongs_to/3

的文档中所述

You should use belongs_to in the table that contains the foreign key. Imagine a company <-> employee relationship. If the employee contains the company_id in the underlying database table, we say the employee belongs to company. In fact, when you invoke this macro, a field with the name of foreign key is automatically defined in the schema for you.

相反,Ecto.Schema.has_one/3 nor Ecto.Schema.has_many/3 均不暗示相应字段的存在。一切都由 link.

的另一端完成

也就是说,

  • students 架构应该有 class_id 字段(已经存在)
  • classes 可能应该有 teacher_id(假设老师可能有几个 class。)要做到这一点,请将 teachers 改为 has_many :classes belongs_to :class classes 更改为 belongs_to :teacher 而不是 has_one :teacher.

是否希望学生属于多个 classes,架构不正确。在 students 的每个记录中存在 class_id 外键意味着每个学生都与这个特定的 class 相关联。你应该删除

belongs_to :classes, Class, foreign_key: :class_id

来自 students,因为它首先将一个学生粘在一个 class 上。然后你必须引入 classes_to_students join schema,如这里所述 Ecto.Schema.many_to_many/3.