表之间的关系

大多数应用程序都是使用数据库的多个表的,而且一些表之间还存在着一些关联。定单
Orders有多个商品项目。一个商品项目将引用一个特殊的产品。一个产品可能属于许多不同
的产品分类目录,而每个分类目录有许多不同的产品。
数据库schema中,这些关系是由基于主键的值来表达的。[关联的另一种风格是,model
对象与它的另一个子类的model之间的关系。在253页的15.3节讨论。]如果一个商品项目
引用了一个产品,则line_items表将就包括一个列,它持有与products表中记录相对应的
主键的值。从数据库的角度来说,line_items表被说成有个外键引用了products表。
但这些都是低级别的。在我们的程序中,我们要处理model对象及它们之间的关系,而
不是数据库的记录和主键列。如果一个定单有许多的商品项目,我们喜欢有多种方式来遍历
它。如果一条商品项目和一个产品关联,我们会说这很简单,例如
price = line_item.product.price
而不是
product_id = line_item.product_id
product = Product.find(product_id)
price = product.price
Active Record可以有rescue子句。它的ORM部分的的魔力就是,它把数据库中比较底
层的外健关系转化成高层的对象间的映射。它处理三种基本的情况。
1、表A的一个记录与表B的一个或0个记录关联
2、表A的一个记录于表B的任意多个记录关联
3、表A的任意多个记录与表B的任意多个记录关联。
我们必须在Active Record处理这些内部表的关系时稍微费点神。这不是Active Record
的缺点,它不可能从含有内部表关系的模式中推断出开发人员的意图。然而,我们所要作的
事情也是很少的。
创建外键
正如前面讨论的,当一个表包含一个外健指向另一个表的主键时两个表是关联的。在下
面的DDL,表 line_items包含一个外键指向表products和表orders。
create table products (
id int not null auto_increment,
title varchar(100) not null,
/* . . . */
primary key (id)
);
create table orders (
id int not null auto_increment,
name varchar(100) not null,
/* ... */
primary key (id)
);
create table line_items (
id int not null auto_increment,
product_id int not null,
order_id int not null,
quantity int not null default 0,
unit_price float(10,2) not null,
constraint fk_items_product foreign key (product_id) references
products(id),
constraint fk_items_order foreign key (order_id) references
orders(id),
primary key (id)
);
值得注意的是:不是外键约束条件来设置关系。这些只是一个数据库的提示而已,它检
查目标表中对应的列值。DBMS一般会忽略这些约束条件。(MySQL有些版本就是这样)因为
开发人员选择从products和orders表中的值来控制列product_id和order_id的主键值,
表之间的关系就是这样非常简单的建立起来了。
查看这个DDL,我们可以看到为什么对Active Record自动猜测表之间的关系是非常困
难的。在line_items表中引用的orders和products表外键看上去是唯一的。但是,
product_id列是一个与product相关联的商品项目。order_id列是多个商品项目和一个order
相关联的。商品项目是order的一部分,但是它引用了product。
这个例子也显示了标准的Active Record命名约定。外键列应该被命名在目标表的类名
之后,并被转化为小写,再附加_id。注意,复数和附加的_id两者的转换,假设外键名字将
由引用的表不同部分组成。如果你有个Active Record model叫Person,它将映射数据库表
people。一个外键引用一些其它表到people表将有个列名叫person_id。
The other type of relationship is where some number of one thing is related
to some number of another thing (such as products belonging to multiple
categories, and categories that contain multiple products). The SQL 约定使用第三个表,叫join的表来处理它。join表包含了一个用于它连接的每个表的外键,所以join表内每行都表示两个其它表之间的连接。
create table products (
id int not null auto_increment,
title varchar(100) not null,
/* . . . */
primary key (id)
);
create table categories (
id int not null auto_increment,
name varchar(100) not null,
/* ... */
primary key (id)
);
create table categories_products (
product_id int not null,
category_id int not null,
constraint fk_cp_product foreign key (product_id) references
products(id),
constraint fk_cp_category foreign key (category_id) references
categories(id)
);
依靠schema,你可能想放置额外的信息给join表,或许是描述被加入的两个类之间自
然关系。
Rails假设一个join表被命名为两个被加入的表名字(名字按字母表次序)。Rails将自
动地找到join表categories_products来连接categories和products。如果你使用一些其
它名字,你需要添加一个声明给Rails,以便它能找到它们。
指定关系
Active Record支持三种表之间的关系类型:一对一,一对多,多对多。你可以通过在
model中加入声明has_one,has_many,belongs_to,和has_and_belongs_to_mang等来表明
关系。
一对一的关系存在于orders和invoices表之间:每个order最多有一个invoice。我
们在Rails这样来声明它
class Order < ActiveRecord::Base
has_one :invoice
. . .
class Invoice < ActiveRecord::Base
belongs_to :order
. . .
定单和商品项目之间一对多关系:可以任意数量的商品项目与一个特定的定单关联。
ails中,我们这样编码
class Order < ActiveRecord::Base
has_many :line_items
. . .
class LineItem < ActiveRecord::Base
belongs_to :order
. . .
我们可能要给我们的products分类。一个product属于多个类别,每个类别包含多个
roduct。这就是多对多的关系,在Rails中这表示
class Product < ActiveRecord::Base
has_and_belongs_to_many :categories
. . .
class Category < ActiveRecord::Base
has_and_belongs_to_many :products
. . .
各种连接声明要比表之间特定关联做的要更多。它们每个都可添加很多方法来帮助在
连接的对象间操作。让我们看看这三个不同种类内部连接上下文环境中的更多细节。我们
将查看考绩个方法。我们在233页图14.5中总结它们,相关的方法可查看RDoc文档。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值