Rails - 建模多个多对多关系

时间:2017-10-16 18:06:53

标签: ruby-on-rails ruby-on-rails-4 many-to-many has-many-through

我有以下用例来创建处理课程的应用程序;

  1. A级课程由Curt in Bos于11/1
  2. 教授
  3. A类由纽约的Curt教授于10月19日
  4. A级由Jane在SF中教授12/5
  5. A级由Jane in Bos在11/1
  6. 教授

    为此应用创建具有多对多关系的模型的最佳方法是什么?

    应用是否有teachings模型属于课程,教师和具有日期列的位置?

2 个答案:

答案 0 :(得分:2)

您想要为每个实体创建一个模型:

  • 教师
  • 位置

然后创建一个我选择调用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:教师,关联表是   为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_foraccepts_nested_attributes是强大的工具。然而,嵌套几个级别的传递属性可以被视为一种反模式,因为它创建了上帝类和意想不到的复杂性。

更好的选择是使用AJAX发送单独的请求来创建教师和位置。它提供了更好的用户体验,更少的验证难题和更好的应用程序设计。

答案 1 :(得分:1)

你走在正确的轨道上。以下是我如何建模这些关系。我们假设你有一个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