【问题标题】:Array of foreign keys in Ecto (Phoenix)Ecto(Phoenix)中的外键数组
【发布时间】:2020-04-22 06:26:02
【问题描述】:

我是网络开发的初学者,所以请原谅我缺乏知识。

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

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

  2. 每位教师都可以参加多个班级

  3. 每个学生都可以参加多个班级。

这是我目前构建的架构:

# 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

这里看起来还不错。但问题是,如何在迁移文件中指定“学生 ID 数组”?以下是迁移函数:

# 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

提前致谢。

【问题讨论】:

    标签: elixir phoenix-framework ecto


    【解决方案1】:

    正如Ecto.Schema.belongs_to/3 的文档中所述

    您应该在包含外键的表中使用belongs_to。想象一下company <-> employee 关系。如果employee 在底层数据库表中包含company_id,我们说employee 属于company。 实际上,当您调用此宏时,会在架构中自动为您定义一个名为外键的字段。

    相反,Ecto.Schema.has_one/3Ecto.Schema.has_many/3 都没有暗示相应字段的存在。一切都在此链接的另一端完成。

    也就是说,

    • students 架构应该有 class_id 字段(已经存在)
    • classes 可能应该有teacher_id(假设一个老师可能有几个班级。)为此,将teachers 更改为has_many :classes 而不是belongs_to :class classes 更改为@ 987654342@ 而不是 has_one :teacher

    无论您希望学生属于多个班级,架构都不正确。在students 的每条记录中存在class_id 外键意味着每个学生都关联了这个特定的班级。你应该删除

    belongs_to :classes, Class, foreign_key: :class_id
    

    来自students,因为它首先将一个学生固定在一个班级。然后你必须引入classes_to_students 加入模式,这里描述Ecto.Schema.many_to_many/3

    【讨论】:

    • 通过架构中的has_many :students, Users.Student。每个学生都有class_id,就是这样。
    • 对不起,我弄错了,所以我删除了评论。我的意思是这如何解决“每个学生都可以成为许多班级的一部分?”我不希望每个学生只上一个班级。
    • 我已经更新了答案。我相信仍然需要交换 classesteachers 以定义谁拥有引用密钥的变化。
    • 太棒了!做到了。
    • 您能否补充一下我应该如何在迁移中反映这些变化?你如何指定many_to_many 关系?我需要将references() 用于many_to_many,还是仅用于belongs_to
    猜你喜欢
    • 2016-12-17
    • 2021-12-26
    • 1970-01-01
    • 2016-10-26
    • 1970-01-01
    • 1970-01-01
    • 2016-10-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多