新手问题 关于 has_many through 关联的查询排序

xiaolai · 2012年10月16日 · 最后由 yedingding 回复于 2012年10月16日 · 3268 次阅读

就像这样:

http://guides.rubyonrails.org/association_basics.html#the-has_many-through-association

class Physician < ActiveRecord::Base
  has_many :appointments
  has_many :patients, :through => :appointments
end

class Appointment < ActiveRecord::Base
  belongs_to :physician
  belongs_to :patient
end

class Patient < ActiveRecord::Base
  has_many :appointments
  has_many :physicians, :through => :appointments
end

现在,我可以

@current_patient_appointments = Appointment.where(patient_id: current_user.id)

然后,我如何才能将查询结果以 physician.name 排序呢?(好像用 join?数据库白痴表示想不明白啊!)

Appointment.where(:patient_id => 2).joins(:physician).order("physicians.name DESC")

like this:

Patient.find(current_user.id).physicians.order name: :desc

这里有个前提,一般情况下,你并不会真的关心那张 appointments 表

谢谢谢谢!

我觉得 Appointment 是不应该直接调用的,你应该忽略它,他只是一个过度 Physician, Patient 之间多对多关联的

我现在的需求是这样的:

我明年暑假要办 Summer School,

  • 共有 12 个课程;
  • 1 天有 4 个时段上课;
  • 每个课程排在某个固定时段,比如,课程 Economics 的时段(schedule)是 2——即第二节课
  • 一个学生在一个时段不可能同时出现在两个教室里,所以,如果他选择了第二节课上 Economics,那么,他就不能同时选择上 Public Policies 这门课(因为这门课也排在第二节)
  • 一个学生可以选 1~4 门课程。

于是,我模仿http://guides.rubyonrails.org/association_basics.html#the-has_many-through-association建立了关联:

user has_many :courses, through: :subscription course has_many :users, through: :subscription subscription belongs_to :user, :course

我卡在这里好 3 天了哈(丢人)

现在我需要一个 form,能同时创建、更新多个 subscriptions(其实最终结果是一个学生/user/的课表/1~4/个 subscriptions)。

然后就不知道怎么干才好了。哈。

不知道我说清楚了没有?

subscriptions

id, user_id, course_id

一个学生在一个时段不可能同时出现在两个教室里,所以,如果他选择了第二节课上 Economics,那么,他就不能同时选择上 Public Policies 这门课(因为这门课也排在第二节)

存入的时候验证 学生编号,课程编号 得唯一

validates_uniqueness_of :user_id, :scope => :course_id

一个学生可以选 1~4 门课程。

存入 subscription 之前先 Subscription.where(:user_id => 1).count 检查是否超过 4 个

你的表单只需要一个下拉选择课程,检查的动作在内部处理,不符合要求的给出提示就好了

课程和时段之间怎么联系?也许应该有个时段模型,然后让它与课程多对多关联

#8 楼 @fsword 我写在 Course 表里面了:

Course: title, description:text, schedule:integer


# 课程
class Course
  # id, name, description

  validates_uniqueness_of :name
end

# 课程安排
class CourseSchedule
  # id, course_id, schedule

  belongs_to :course
end

class Subscription
  # id, course_schedule_id, user_id
  belongs_to :user
  belongs_to :course_schedule

  validates_uniqueness_of :course_schedule_id, :scope => :user_id
end

# 获取每节课的信息
@courses1 = CourseSchedule.where(:schedule => 1)
@courses2 = CourseSchedule.where(:schedule => 2)
@courses3 = CourseSchedule.where(:schedule => 3)

我认为这个表单最重要的功能解决选课冲突问题,大概有两种方式判断冲突,前端判断或者服务端判断,我只能说大概思路,具体要实现一遍才能说清楚:

A: 前端判断,用 JavaScript 的 hash 来记录所有课时表,然后在选择的时候通过 onchange event 来判断并查表决定其他菜单中剩下 available 的课程,更新并隐藏掉冲突的课程。

B: 后端判断,表单只能允许学生一次添加一个课时,当添加了第一个课程后,比如 First Class,通过后端判断并计算出 available 的其他课程,然后在让学生添加第二个课程,以此类推,学生一共可以添加四个课时选择。

谢谢大家

我觉得划分成 4 个 class 比较好,也许 5 个

1 Course:代表一个课目,比如 econmics, computer sience has_many :lesson 一个 course 有很多节课 分在不同的时间

2 Schedule 就是 每个记录针对一节课 每天 4 个节课就是 4 个记录 has_many :lesson

3 Lesson belongs_to :course belongs_to :schedule has_many :relationships has_many :students, :through => :relationships

(其实 schedule 这个 class 不要也行 就用一个字符串表示 比如 08-01-a 表示 8 月 1 号第一节课)

4 Student has_many :relationships has_many :lessons, :through => :relationships

5 Relationship belongs_to :student belongs_to :lesson

不知是否符合需求,或者搞得太复杂了?呵呵

又重新看了一下,楼主的问题可能集中在冲突检查上,如果这样的话,@lgn21st 的建议基本上应该就够了

谢谢大家!重新用其他的关键字 Google 了一下,还是找回 railscasts.com 了。http://railscasts.com/episodes/17-habtm-checkboxes-revised 这一集里面有相关的解决方案。

#15 楼 @xiaolai @huacnlee 给的方案基本差不多了,具体可以还是看真实的需求。@lgn21st 给的建议主要集中在你如何写 validation 来保护

需要 登录 后方可回复, 如果你还没有账号请 注册新账号