Rails - 建立多对多关系
问题描述:
我有以下用例来创建处理课程的应用程序;通过简略的教导Rails - 建立多对多关系
- 类A由简略教导的Bos上11/1
- A类中NY上10/19
- 类A由简SF讲授12/5
- A类是由简博斯教授在11/1
什么是与许多为这个应用程序一对多关系创建模型的最佳方式?
应该有teachings
模型属于课程,教师和地点与日期列?
答
你想要的是创建为每个实体模型:
- 课程
- 教师
- 位置
然后创建我已经选择调用课各种各样的加盟模式:
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
我一直在玩这个结构模型,但我注意到的是,当提交与fields_for :位置和fields_for:教练的课程时,关联表为 为course_id + instructor_id创建两个单独的条目,course_id + location_id,我期望为course_id,instructor_id,location_id指定一个条目。任何想法为什么可能发生?
当您隐式创建连接模型时,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发送单独的请求来创建教师和位置。它提供了更好的用户体验,更少的验证问题和更好的应用程序设计。
答
您正处于正确的轨道上。以下是我将如何建模这些关系。比方说,你有一个Teacher
模型,Course
模型和TeacherCourses
模型,这将是我们参加的教师和课程之间表:
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
表也有位置属性区分来自同一课程/教师记录组合:
create_table :teacher_courses do |t|
t.integer :teacher_id
t.integer :course_id
t.string :location
t.timestamps
end
感谢这一点 - 我一直在玩这个模型的结构,但我注意到当用'fields_for:locations'和'fields_for:instructors'提交课程时,'associations'表创建了两个独立的course_id + instructor_id,course_id + location_id的条目,我期望course_id,instructor_id,location_id的单个条目。任何想法为什么可能发生? –
因为你做错了。当连接模型不仅仅是一个双向连接模型时,你不能隐式创建它,因为ActiveRecord只能追踪一个关系。看我的编辑。 – max
感谢您的信息,我不知道Rails有三种方式连接的限制。所以要做到这一点的唯一方法是分别创建位置和老师,然后使用集合选择来关联它们? –