您想要的是为每个实体创建一个模型:
然后您可以创建一种联接模型,我选择称之为“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
我一直在使用这个结构来创建模型,但我发现当使用fields_for :locations和fields_for :instructors提交课程时,关联表会为course_id + instructor_id、course_id + location_id创建两个单独的条目,我期望只有一个条目包含course_id、instructor_id和location_id。你认为可能是什么原因导致了这种情况?
当隐式地创建join model时,ActiveRecords只会跟踪一个关联。要进行三方连接,您需要显式地创建join model。
<%= 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发送单独的请求来创建教师和位置。这样做可以提供更好的用户体验,减少验证问题,并改善应用程序设计。