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-连接多张表之单表继承的更多相关文章

  1. python 存储引擎 mysql(库,表, 行) 单表多表操作 (foreign key) sql_mode pymysql模块讲解

    ##################总结############### mysql 常用数据类型 整型:tinyint  int(42亿条左右)  bigint 小数:float double dec ...

  2. django(七)之数据库表的单表-增删改查QuerySet,双下划线

    https://www.cnblogs.com/haiyan123/p/7738435.html https://www.cnblogs.com/yuanchenqi/articles/6083427 ...

  3. django之数据库表的单表查询

    一.添加表记录 对于单表有两种方式 # 添加数据的两种方式 # 方式一:实例化对象就是一条表记录 Frank_obj = models.Student(name ="海东",cou ...

  4. Django框架----数据库表的单表查询

    一.添加表记录 对于单表有两种方式 # 添加数据的两种方式 # 方式一:实例化对象就是一条表记录 Frank_obj = models.Student(name ="海东",cou ...

  5. python 之 数据库(修改表、复制表、删除表、单表查询)

    10.8 修改表.复制表.删除表 10.81 修改表 alter table . 修改表名 alter table 表名 rename 新表名; . 增加字段 alter table 表名 add 字 ...

  6. Mysql常用表操作 | 单表查询

    160905 常用表操作 1. mysql -u root -p 回车 输入密码   2. 显示数据库列表 show databases     3. 进入某数据库 use database data ...

  7. $Django orm增删改字段、建表 ,单表增删改查,Django请求生命周期

    1 orm介绍  ORM是什么   ORM 是 python编程语言后端web框架 Django的核心思想,“Object Relational Mapping”,即对象-关系映射,简称ORM.  一 ...

  8. python开发mysql:表关系&单表简单查询

    一 一对多,多对一 1.1 建立多对一 ,一对多的关系需要注意 先建立被关联的表,被关联的字段必须保证时唯一的 在创建关联的表,关联的字段一定是可以重复的 1.2 示例: 出版社 多对一,多个老师可能 ...

  9. day42——外键的限制和解决方法、外键的三种约束模式、修改表(单表查询)

    day42 外键的限制和解决方法 可以添加外键关联的那个字段可以是 被唯一(unique)约束的字段 或者 主键 限制:+ 由于外键的使用,致使多个表之间产生了联系,当我们对这些表进行更新或删除操作的 ...

随机推荐

  1. 【luogu P1186 玛丽卡】 题解

    题目链接:https://www.luogu.org/problemnew/show/P1186 邻接表开大开小真的奇妙,毒瘤玩意,再您妈的见. #include <queue> #inc ...

  2. Java 基础总结

    Java基础总结 jdk:Java的开发环境与部署环境jre:Java的运行环境 Java数据类型分为:基本类型和引用类型 基本类型:①整数类型 byte   short   int   long 默 ...

  3. Object C学习笔记20-结构体(转)

    在学习Object C中的过程中,关于struct的资料貌似非常少,查阅了C方面的资料总结了一些学习心得! 一. 定义结构 结构体是一种数据类型的组合和数据抽象.结构体的定义语法如下: struct ...

  4. Ionic的项目结构(angluar js)

    Hybird HTML5 App(移动应用开发)之3.Ionic的项目结构 前面使用命令ionic start myapp下载了默认的Ionic应用程序,下面我们打开应用程序项目,来分析一下Ionic ...

  5. AOJ 0531 坐标离散化

    涂色:(日文题目,自己翻译成了中文)为了宣传信息竞赛,要在长方形的三合板上喷油漆来制作招牌.三合板上不需要涂色的部分预先贴好了护板.被护板隔开的区域要涂上不同的颜色,比如上图就应该涂上5种颜色. 请编 ...

  6. Java基础题:集合、String、性能、线程

    转载自:Java基础题 https://yq.aliyun.com/articles/601786?utm_content=m_1000001149

  7. Jmeter的简单介绍

    Apache JMeter是Apache组织开发的基于Java的压力测试工具.用于对软件做压力测试,它最初被设计用于Web应用测 试但后来扩展到其他测试领域. 它可以用于测试静态和动态资源例如静态文件 ...

  8. python的字典数据类型及常用操作

    字典的定义与特性 字典是Python语言中唯一的映射类型. 定义:{key1: value1, key2: value2} 1.键与值用冒号“:”分开: 2.项与项用逗号“,”分开: 特性: 1.ke ...

  9. MAthJax入门教程(五分钟上手)

    最近在研究,在页面中显示一些数学公式.搞得我很头疼. 据说MathJax会统一这已领域.所以去学了学.网上教程特别多.繁杂. 说的清楚的特别少. 我是这么跑通的,: 1.在官网下载代码地址为:http ...

  10. JavaSE 第二次学习随笔(五)

    /* * 中文乱码出现的情况研究 * 注意点:乱码解决的办法是再编码再解码 * 但是如果是编码出错了,无法解决.如果是解码出错了,可以利用再编码再解码 * * * 编码 解码 结果 * GBK utf ...