我们知道,在rails中,habtm和polymorphic都是非常好的东东,特别是后者,可以说是rails的ORM中非常强大的功能。《Agile Web Development with Rails》虽然详细讲述了habtm和polymorphic关联,也讲了如何把模型类映射为连接表,但是并没有讲如何把habtm和polymorphic一起使用做一个介绍。这里我就来简单说一下。
还是出自真实项目中的需求,项目是全国大学本科教学评估支持系统,说白了就是大学用来支持本科教学评估的东西。里面有这样一个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
分享到:
- 2007-10-05 15:19
- 浏览 2687
- 评论(0)
- 论坛回复 / 浏览 (0 / 2769)
- 查看更多
相关推荐
在Ruby on Rails(Rails)框架中,数据库表之间的关联是数据模型的核心部分,它使得开发者可以轻松地处理复杂的数据库操作。Rails提供了四种基本的关联类型:` belongs_to`、` has_one`、` has_many` 和 `has_and_...
cakephp2.x-habtm-示例cakephp2.x-habtm-example示例说明如何使用CakePHP 2.x保存和验证两个模型之间的HABTM关系(此代码中使用的版本实际上是2.2) 我们使用两种模型:Post和Tag。 一个帖子与N个标签相关,一个标签...
在CakePHP框架中,Model关联对象的使用是构建复杂数据模型和实现数据库间关系的关键特性。这使得开发者可以通过面向对象的方式来处理数据,提高代码的可读性和可维护性。以下是四种主要的关联类型及其详细解释: 1....
3. **常数(Constants)**: 在模型中定义常数通常用于设置与数据库交互时的属性,如批量操作的默认值(`HABTM_KEY`)、状态值(`STATUS_ACTIVE`)等。这有助于提高代码的可读性和可维护性。 4. **保留字段...
Ubuntu命令技巧手册》是专为Ubuntu用户设计的一份实用指南,它涵盖了广泛的操作系统管理、文件处理、网络通信及系统维护等方面的命令行操作技巧。Ubuntu是一个基于Debian的开源Linux发行版,以其用户友好性和强大的命令行工具而受到全球开发者和用户的喜爱。通过熟练掌握这些命令技巧,用户可以更高效地在Ubuntu环境中工作。 手册首先会介绍Ubuntu的基本概念,包括终端的使用和命令行的基本语法。在Linux系统中,终端是执行各种系统级任务的核心工具,用户可以通过键盘输入命令来执行操作,而无需图形化界面。掌握如何打开终端(如通过快捷键Ctrl+Alt+T)以及基本的命令行导航(如cd、ls、pwd)是使用Ubuntu的第一步。 文件和目录管理是Ubuntu命令行中的重要部分。例如,`mkdir`用于创建新目录,`touch`用于创建新文件,`cp`和`mv`分别用于复制和移动文件或目录,而`rm`则用于删除。了解这些命令的选项,如递归操作(-r)和强制删除(-f),能帮助用户更灵活地管理文件系统。
Stylus是一款能改变网站样式的样式管理器(谷歌浏览器插件)
springboot项目基于Spring与Vue的疫情居家检测管理系统的设计与实现代码,含有完整的源码和报告文档
文本框说明文字循环PPT模板
图表分类ppt
Linear Algebra and Its Applications - 5th Edition - David C. Lay《线性代数及其应用》 能复制。英文版本。
MATLAB环境下一种自适应Chirp模态分解方法。 算法运行环境为Matlab r2018a,可用于一维时间序列分解,时频分析,故障诊断,特征提取等。 算法可迁移至金融时间序列,地震 微震信号,机械振动信号,声发射信号,电压 电流信号,语音信号,声信号,生理信号(ECG,EEG,EMG)等一维时间序列信号。 压缩包=程序+数据+参考。
信捷PLC程序 信捷XDM系列PLC程序,信捷触摸屏程序 双轴圆弧插补三轴画圆程序
项目资源包含:可运行源码+sql文件+文档 源码都是精心调试,有文档,可以部署,有费用,谢谢支持。 适用人群:学习不同技术领域的小白或进阶学习者;可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 项目具有较高的学习借鉴价值,也可拿来修改、二次开发。 有任何使用上的问题,欢迎随时与博主沟通,博主看到后会第一时间及时解答。 开发语言:Java 框架:SpringBoot 技术:Vue JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7 数据库工具:Navicat11 开发软件:eclipse/myeclipse/idea Maven包:Maven3.3.9 系统是一个很好的项目,结合了后端服务(SpringBoot)和前端用户界面(Vue.js)技术,实现了前后端分离。
资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、大作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、大作业、项目初期立
基于单目视觉原理,研究目标图像的预处理、识别、定位方法与测距模型,设计实现一个目标识别与定位测距原型系统。_MonocularVisionRanging
基于留出法、k折交叉验证和留一法的多种机器学习模型对比(用于分类)MATLAB程序:代码中共包含决策树(DT)、判别分析(DA)、集成树(ET)、高斯混合模型(GMM)、k近邻(KNN)、多分类支持向量机(MSVM)、支持向量机(SVM)、随机森林(RF)八种机器学习模型,可以任意选择,分别用留出法、k折交叉验证和留一法进行分类效果对比。 代码注释清楚。 main为主程序,读取EXCEL数据。 很方便,容易上手。 温馨提示:联系请考虑是否需要,程序代码,一经出,概不 。
SPOTIFY - Culture Next Report_CAIG
项目资源包含:可运行源码+sql文件+ 源码都是精心调试,,可以部署,有费用,谢谢支持。 适用人群:学习不同技术领域的小白或进阶学习者;可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 项目具有较高的学习借鉴价值,也可拿来修改、二次开发。 有任何使用上的问题,欢迎随时与博主沟通,博主看到后会第一时间及时解答。 开发语言:Java 框架:SpringBoot 技术:Vue JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7 数据库工具:Navicat11 开发软件:eclipse/myeclipse/idea Maven包:Maven3.3.9 系统是一个很好的项目,结合了后端服务(SpringBoot)和前端用户界面(Vue.js)技术,实现了前后端分离。
springboot项目基于Web的课程设计选题管理系统,含有完整的源码和报告文档
ThinkPHP是一个高性能且功能完备的轻量级PHP开发框架,具备众多原创特性,并秉持“大道至简”的开发理念,致力于以最少的代码实现更多功能,旨在简化并加速WEB应用的开发流程。自1.*版本起,该框架便不再兼容PHP4,从而使其架构与实现更为灵活与简洁。2.0版本在前序版本的基础上,经过全面重构与持续优化,达到了新的高度,满足企业级与门户级开发的标准。 以下是ThinkPHP相关文档的列表: - ThinkPHP 2.0 Q&A.chm - ThinkPHP-2.0-API.chm - ThinkPHP2.0完全开发手册.chm - ThinkPHP2.0开发技巧.chm - ThinkPHP2.1 RBAC使用和示例操作.chm - ThinkPHP2.1 完全开发手册.chm - ThinkPHP2.1 常见问题&开发技巧.chm - ThinkPHP2.1 自定义标签示例说明.chm