ActiveRecord-连接多张表之单表继承
ActiveRecord-连接多张表之单表继承
1. 基本概念
Rails提供了两种机制,可以将复杂的面向对象模型映射为关系模型,即所谓的单表继承(single-table inheritance)和多态关联(polymorphic associations,也有人称为多表继承)。
2. 单表继承
在使用面向对象开发时,经常会用到类和继承,如应用程序中涉及不同角色的人员(People):顾客(Customer)、员工(Employee)和经理(Manager)等等。其中有一些属性是共有的,另一些属性是特有的。因此,创建模型:Customer类和Employee类,且都是People的子类,Manager类是Employee的子类。子类会继承父类的所有属性和行为。
这些都是代码中的模型体现,在关系型数据库是如何体现的?见如下代码:
# model的定义
class People
# 迁移文件的定义,即关系型数据库的体现
create_table :people, :force => true do |t|
t.column :type, :string
# common attributes
t.column :name, :string
t.column :email, :string
# attributes for type=Customer
t.column :balance, :decimal, :precision => 10, :scale => 2
# attributes for type=Employee
t.column :reports_to, :integer
t.column :dept, :integer
# attributes for type=Manager
# none
end
# 添加人员
boss = Manager.create({name: 'Jobs', email: 'jobs@apple.com', dept: 1})
empl = Employee.new({name: 'David', email: 'david@apple.com', dept: 2})
empl.boss = boss
empl.save
user = Customer.create({name: 'Jim', email: 'jim@rails.com', balance: 100})

由上面的代码可以看出类定义中使用了继承,而对于不同角色的人员,均保存于people表,对于boss和empl对象,都是没有user的balance属性的,即这两个对象的balance字段都是null,而对于user对象的dept和reports_to字段同样是null,这样就实现了一个单表继承,相比于我们使用各种其它方法会简单很多。但是问题是:
2.1 ActiveRecord如何如此简单的提供了单表继承?
通过迁移文件中可以看到,在people表中添加了type字段。通过上图也可以看到,每条记录的type字段都有值,而且为用户的角色。ActiveRecord是约定好了使用type字段来描述对象所属的类型。
针对此问题,可以详见Martin Fowler在《企业应用架构模式》的介绍。
2.2 如果一个新加入的开发者使用People添加了人员呢?
是的,也许一个新加入项目组的同学使用People添加了人员,即使是测试,也会感觉到代码不是那么严谨,例如:
god = Person.create({name: 'God', email: 'god@god.god'})

发生了什么?God真的是神啊,type为空,所以,我们一定不想在表中见到神,按如下三种方法均可以解决:
- 在People中实现一个名为abstract_class?的类方法,并使其返回true,这样,就可以达到目的了。不过它带来的问题是:1.ActiveRecord永远不会尝试寻找对应于抽象类的数据库表,这是对我们有利的,2.抽象类的子类会被当作各自独立的ActiveRecord模型类,即各自映射到一张独立的数据库表。这就达不到我们对公共属性抽取的目的了。这种方法不完美
- 使用Ruby模块来包含这些需要共享的功能,然后将模块混入所谓的子类。这是书中提供的方法,也感觉不完美,没有了继承的感觉
- 能否在父类中添加什么使其只可读不可写呢?
2.3 单表继承的优点和缺点
单表继承中所有的属性都存在于一张表中,这样真的好吗?如果子类存在的差异较大,且属性数据较大,如果仍然存在于同一张表,就会产生很多问题。这时可以学习多态继承了。
5. 参考
- 《Web开发敏捷之道》第2版#P341-连接多张表
ActiveRecord-连接多张表之单表继承的更多相关文章
- python 存储引擎 mysql(库,表, 行) 单表多表操作 (foreign key) sql_mode pymysql模块讲解
##################总结############### mysql 常用数据类型 整型:tinyint int(42亿条左右) bigint 小数:float double dec ...
- django(七)之数据库表的单表-增删改查QuerySet,双下划线
https://www.cnblogs.com/haiyan123/p/7738435.html https://www.cnblogs.com/yuanchenqi/articles/6083427 ...
- django之数据库表的单表查询
一.添加表记录 对于单表有两种方式 # 添加数据的两种方式 # 方式一:实例化对象就是一条表记录 Frank_obj = models.Student(name ="海东",cou ...
- Django框架----数据库表的单表查询
一.添加表记录 对于单表有两种方式 # 添加数据的两种方式 # 方式一:实例化对象就是一条表记录 Frank_obj = models.Student(name ="海东",cou ...
- python 之 数据库(修改表、复制表、删除表、单表查询)
10.8 修改表.复制表.删除表 10.81 修改表 alter table . 修改表名 alter table 表名 rename 新表名; . 增加字段 alter table 表名 add 字 ...
- Mysql常用表操作 | 单表查询
160905 常用表操作 1. mysql -u root -p 回车 输入密码 2. 显示数据库列表 show databases 3. 进入某数据库 use database data ...
- $Django orm增删改字段、建表 ,单表增删改查,Django请求生命周期
1 orm介绍 ORM是什么 ORM 是 python编程语言后端web框架 Django的核心思想,“Object Relational Mapping”,即对象-关系映射,简称ORM. 一 ...
- python开发mysql:表关系&单表简单查询
一 一对多,多对一 1.1 建立多对一 ,一对多的关系需要注意 先建立被关联的表,被关联的字段必须保证时唯一的 在创建关联的表,关联的字段一定是可以重复的 1.2 示例: 出版社 多对一,多个老师可能 ...
- day42——外键的限制和解决方法、外键的三种约束模式、修改表(单表查询)
day42 外键的限制和解决方法 可以添加外键关联的那个字段可以是 被唯一(unique)约束的字段 或者 主键 限制:+ 由于外键的使用,致使多个表之间产生了联系,当我们对这些表进行更新或删除操作的 ...
随机推荐
- asp.net 过滤器
asp.net 制作过滤器原理:重写ASP.net管道事件 1.通过HttpApplicationFactory创建一个HttpApplication对象,负责处理整个请求. 2.调用ProcessR ...
- HDU 1226 超级密码(数学 bfs)
传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1226 超级密码 Time Limit: 20000/10000 MS (Java/Others) ...
- 两台电脑在不同情况下ping的情况
两台计算机(交叉连接) 同一网段 ,可以ping通.不同网段,不可以 两台计算机通过一台交换机连接 同一网段 ,可以ping通.不同网段,不可以.同一网段,同一Vlan,不可以. 综上:跨网段通信,必 ...
- 名词解释-FrameWork
直接翻译的意思是架构,但这样说可能不懂,下面我从两个方面来给你说吧: 一是比喻来说,假设你现在要盖楼房,framework就好比一个建筑公司,它里面有专门采集石料的,专门的租夹板的,专门的磨砂,搬砖的 ...
- chromium之non_thread_safe
先看看介绍 // A helper class used to help verify that methods of a class are // called from the same thre ...
- Spring Boot2.4双数据源的配置
相较于单数据源,双数据源配置有时候在数据分库的时候可能更加有利 但是在参考诸多博客以及书籍(汪云飞的实战书)的时候,发现对于spring boot1.X是完全没问题的,一旦切换到spring boot ...
- jQuery Ajax请求后台数据并在前台接收
1.ajax基本语法 <script> $(function(){ $('#sub').click(function(){ var username=$('#username').val( ...
- 03 shell编程之case语句与函数
本文所有内容均来自当年博主当年学习笔记,若有不足欢迎指正 Shell编程之case语句与函数 学习目标: 掌握case语句编程 掌握shell函数的使用 目录结构: Case语句 Case语句的作用 ...
- jqGrid使用手册
JQGrid是一个在jquery基础上做的一个表格控件,以ajax的方式和服务器端通信. JQGrid Demo 是一个在线的演示项目.在这里,可以知道jqgrid可以做什么事情.jQgrid 使用详 ...
- ExtJS动态切换主题
ExtJS动态切换主题 在Sencha Cmd构建的Ext程序中怎么去动态切换主题,目前看好像只能单一切换,但是在官网文档找到了答案 Resource Management在上一节通过 ...