浏览 2768 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-10-05
还是出自真实项目中的需求,项目是全国大学本科教学评估支持系统,说白了就是大学用来支持本科教学评估的东西。里面有这样一个use case: 评估中需要召开座谈会,参加的人有:专家、教师、学生...(反正就是学校里面的各色人等),并且参加座谈会的各种人都可以是多个。这样就有了这样一个多对多的数据关系:多个人可以参加多个座谈会,参加者的类别是不一样的(需要polymorphic)。 让我们仔细看看这个use case,其实它还是挺微妙有趣的。如果不考虑polymorphic,那么这里显然就是一个标准的habtm关系,那么我们就建立三张表users、symposia和symposia_users,然后两边用habtm关联一下就好了。 但是如果要考虑polymorphic,就没有这么简单了。这里最主要的问题是habtm本身不支持polymorphic选项,支持polymorphic选项的只有belongs_to。那么我们就不得不把habtm拆成has_many和belongs_to两部分了。 先创建关联表attendances及其响应的model: # create_attendances.rb-------------------------------------- create_table :attendances do |t| t.column :attendee_id, :integer t.column :attendee_type, :string t.column :symposium_id, :integer end # attendance.rb---------------------------------------------- class Attendance < ActiveRecord::Base belongs_to :attendee, :polymorphic => true belongs_to :symposium end 其中的attendee就会多态地关联到专家、教师、学生等人员身上。 然后再配置symposium.rb、expert.rb、teacher.rb、student.rb: # symposium.rb------------------------------------------------ class Symposium < ActiveRecord::Base has_many :attendances has_many :experts, :through => :attendances, [b]:source => :attendee, :source_type => 'Expert'[/b] has_many :teachers, :through => :attendances, :source => :attendee, :source_type => 'Teacher' has_many :students, :through => :attendances, :source => :attendee, :source_type => 'Student' end # teacher.rb-------------------------------------------------- class Teacher < ActiveRecord::Base has_many :attendances, :as => :attendee has_many :symposia, :through => :attendances end # expert.rb和student.rb与teacher.rb相同------------------------ 以上代码都比较好理解,就是其中的source和source_type选项可能不是很常见,看看ActiveRecord的doc就会明白,source用来指定关联到attendance的哪个属性上(当然就是attendee),而source_type则是在使用了polymorphic的情况下指定attendee的具体类型。 经过以上的配置,整个model的关系就建立起来了,不过在使用这些关系的时候仍需注意一点。假设我们要新建一个座谈会,参与者有专家1、2,教师1、2和学生1、2,代码要怎么写呢?很多人可能都会想是: symposium = Symposium.new(:name => "座谈会1") symposium.experts << Expert.find(1) << Expert.find(2) symposium.teachers << Teacher.find(1) << Teacher.find(2) symposium.students << Student.find(1) << Student.find(2) symposium.save 不过这样写是不对的,会得到如下错误: ActiveRecord::HasManyThroughCantAssociateNewRecords: Cannot associate new records through 'Symposium#attendances' on '#'. Both records must have an id in order to create the has_many :through record associating them. 意思是说symposium和teacher(expert、student)之间的关联要通过attendance,而现在还没有attendance呢(即both records must have an id)。那么要如何先把要用的attendance创建出来呢?对,在建立关系前先创建并保存symposium,这样就间接地提前创建了需要用的attendance。 begin Symposium.transaction do symposium = Symposium.new(:name => "座谈会1") symposium.save! [b]# 这句很重要[/b] symposium.experts << Expert.find(1) << Expert.find(2) symposium.teachers << Teacher.find(1) << Teacher.find(2) symposium.students << Student.find(1) << Student.find(2) symposium.save! end rescue # 处理事务中的异常... end 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |