Rails - 建模多个多对多关系
Rails - modeling multiple many to many relationships
我有以下用于创建处理课程的应用程序的用例;
- Class 11月1日在Bos由Curt教授A
- Class A 于 10 月 19 日在纽约由 Curt 授课
- Class 12/5 SF简教A
- Class 11月1日Jane在Bos教A
为此应用程序创建具有多对多关系的模型的最佳方法是什么?
应用程序是否应该有一个属于课程、教师和地点的 teachings
模型,其中有一列是日期?
你走在正确的轨道上。以下是我将如何模拟这些关系。假设您有一个 Teacher
模型、一个 Course
模型和一个 TeacherCourses
模型,它们将成为我们教师和课程之间的连接 table:
class Teacher < ActiveRecord::Base
has_many :courses, through: :teacher_courses
end
class Course < ActiveRecord::Base
has_many :teachers, through: :teacher_courses
end
class TeacherCourse < ActiveRecord::Base
belongs_to :course
belongs_to :teacher
end
您的 teacher_courses
table 也将具有位置属性,将记录与相同的 course/teacher 组合区分开来:
create_table :teacher_courses do |t|
t.integer :teacher_id
t.integer :course_id
t.string :location
t.timestamps
end
你想要的是为每个实体创建一个模型:
- 课程
- 老师
- 位置
然后创建一个连接模型,我选择将其命名为 Lesson:
class Course < ActiveRecord::Base
has_many :lessons
has_many :locations, through: :lessons
has_many :teachers, through: :lessons
end
class Lesson < ActiveRecord::Base
belongs_to :course
belongs_to :teacher
belongs_to :location
end
class Teacher < ActiveRecord::Base
has_many :lessons
has_many :courses, through: :lessons
end
class Location < ActiveRecord::Base
has_many :lessons
has_many :courses, through: :lessons
has_many :teachers, through: :lessons
end
I've been playing with this structure for the models but what I
noticed is that when submitting the course with a fields_for
:locations and a fields_for :instructors, the associations table is
creating two separate entries for course_id + instructor_id, course_id
+ location_id, I would expect a single entry for course_id, instructor_id, location_id. Any thoughts as to why that might happen?
当您隐式创建连接模型时,ActiveRecords 只会跟踪一个关联。要进行三向连接,您需要显式创建连接模型。
<%= form_for(@course) do |f| %>
<div class="field>
<% f.label :name %>
<% f.text_field :name %>
</div>
<fieldset>
<legend>Lesson plan<legend>
<%= f.fields_for(:lessons) do |l| %>
<div class="field>
<% l.label :name %>
<% l.text_field :name %>
</div>
<div class="field">
<% l.label :starts_at %>
<% l.datetime_select :starts_at %>
</div>
<div class="field">
<% l.label :teacher_ids %>
<% l.collection_select :teacher_ids, Teacher.all, :id, :name, multiple: true %>
</div>
<div class="field">
<% l.label :location_id %>
<% l.collection_select :location_id, Location.all, :id, :name %>
</div>
<% end %>
</fieldset>
<% end %>
fields_for
和 accepts_nested_attributes
是强大的工具。然而,传递向下嵌套多个级别的属性可以被视为某种反模式,因为它创造了上帝 类 和意想不到的复杂性。
更好的替代方法是使用 AJAX 发送单独的请求来创建教师和位置。它提供了更好的用户体验、更少的验证难题和更好的应用程序设计。
我有以下用于创建处理课程的应用程序的用例;
- Class 11月1日在Bos由Curt教授A
- Class A 于 10 月 19 日在纽约由 Curt 授课
- Class 12/5 SF简教A
- Class 11月1日Jane在Bos教A
为此应用程序创建具有多对多关系的模型的最佳方法是什么?
应用程序是否应该有一个属于课程、教师和地点的 teachings
模型,其中有一列是日期?
你走在正确的轨道上。以下是我将如何模拟这些关系。假设您有一个 Teacher
模型、一个 Course
模型和一个 TeacherCourses
模型,它们将成为我们教师和课程之间的连接 table:
class Teacher < ActiveRecord::Base
has_many :courses, through: :teacher_courses
end
class Course < ActiveRecord::Base
has_many :teachers, through: :teacher_courses
end
class TeacherCourse < ActiveRecord::Base
belongs_to :course
belongs_to :teacher
end
您的 teacher_courses
table 也将具有位置属性,将记录与相同的 course/teacher 组合区分开来:
create_table :teacher_courses do |t|
t.integer :teacher_id
t.integer :course_id
t.string :location
t.timestamps
end
你想要的是为每个实体创建一个模型:
- 课程
- 老师
- 位置
然后创建一个连接模型,我选择将其命名为 Lesson:
class Course < ActiveRecord::Base
has_many :lessons
has_many :locations, through: :lessons
has_many :teachers, through: :lessons
end
class Lesson < ActiveRecord::Base
belongs_to :course
belongs_to :teacher
belongs_to :location
end
class Teacher < ActiveRecord::Base
has_many :lessons
has_many :courses, through: :lessons
end
class Location < ActiveRecord::Base
has_many :lessons
has_many :courses, through: :lessons
has_many :teachers, through: :lessons
end
I've been playing with this structure for the models but what I noticed is that when submitting the course with a fields_for :locations and a fields_for :instructors, the associations table is creating two separate entries for course_id + instructor_id, course_id + location_id, I would expect a single entry for course_id, instructor_id, location_id. Any thoughts as to why that might happen?
当您隐式创建连接模型时,ActiveRecords 只会跟踪一个关联。要进行三向连接,您需要显式创建连接模型。
<%= form_for(@course) do |f| %>
<div class="field>
<% f.label :name %>
<% f.text_field :name %>
</div>
<fieldset>
<legend>Lesson plan<legend>
<%= f.fields_for(:lessons) do |l| %>
<div class="field>
<% l.label :name %>
<% l.text_field :name %>
</div>
<div class="field">
<% l.label :starts_at %>
<% l.datetime_select :starts_at %>
</div>
<div class="field">
<% l.label :teacher_ids %>
<% l.collection_select :teacher_ids, Teacher.all, :id, :name, multiple: true %>
</div>
<div class="field">
<% l.label :location_id %>
<% l.collection_select :location_id, Location.all, :id, :name %>
</div>
<% end %>
</fieldset>
<% end %>
fields_for
和 accepts_nested_attributes
是强大的工具。然而,传递向下嵌套多个级别的属性可以被视为某种反模式,因为它创造了上帝 类 和意想不到的复杂性。
更好的替代方法是使用 AJAX 发送单独的请求来创建教师和位置。它提供了更好的用户体验、更少的验证难题和更好的应用程序设计。