一对一关系(或者更正确的是,一对零或一关系)由一个表内的行中的一个外键实现,它
至少引用了另一个表的单个行。上面图显示了order和invoice之间的一对一关系:一个order可以没有invoice引用它或者只有一个invoice引用它。
在Active Record内,我们通过添加声明has_one :invoice给类Order来表示这种关系 ,同时,添加belongs_to

rder给类Invoice。(记住belongs_to行必须出现在用于包含外键的表的model内。)你可以从关联的任一端用一个order来关联一个invoice。
你可以告诉一个order,它有一个invoice与它关联,或者你可以告诉invoice,它与一
个order关联。这两者是相等的。区别是它们保存对象到数据库的方式。如果你给一个对象
赋值一个has_one关联一个现有对象,那个被关联的对象将被自动地保存。
an_invoice = Invoice.new(...)
order.invoice = an_invoice # invoice gets saved
相反,如果你给一个新对象赋值一个belongs_to 关联,它将不会被自动保存。
order = Order.new(...)
an_invoice.order = order # Order will not be saved
这儿有个区别。如果你给一个新对象赋值has_one关联时,如果这儿已经存在一个子对
象,那个现有对象将被更新来移除与父行关联的外键(外键将被设置为零)。这在图14.4中显
示。
最后,这是危险的。如果子行不能被保存(例如,因它确认失败),Active Record将不
会抱怨—你将得不到暗示,行不能被添加到数据库。对于这个原因,我们强烈推荐代替先前
代码,你写出
invoice = Invoice.new
# fill in the invoice
unless invoice.save!
an_order.invoice = invoice
save!方法在失败时抛出一个异常,所以至少你将知道有些东西出错误了。
belongs_to() 声明belongs_to()声明给定的类是本身类的父类。尽管belongs_to可能不是我们考虑这种关
系时最先想到的词,但是Active Record的约定是包含外键的表属于它引用的表。如果这有
助于编码的话,你应该把references当成belongs_to使用。
我们假定父类的名字是属性名大小写混合的单数形式,外键字段是附加_id的属性名的
单数形式。所以,给出下面代码
class LineItem < ActiveRecord::Base
belongs_to :product
belongs_to :invoice_item
end
Active Record把商品项目和类Product,InvoiceItem相关联。(特别注意:其中的单
复数形式的变化。)其中隐含的意思是,它使用了外键product_id,invoice_item_id来引用表products,invoice_items的id列。
还可以覆写这些,其它人会假设传给belongs_to()一个选项的哈希表散列值改变这些
定。
class LineItem < ActiveRecord::Base
belongs_to :paid_order,
:class_name => "Order",
:foreign_key => "order_id",
:conditions => "paid_on is not null"
end
这个例子中,我们创建了一个paid_order的关联,它是类Order的引用(对应的表
orders)。这连接是通过order_id外键建立的,但是它还是有条件限制的,如果目标行的
paid_on列不为null,它将找到一个定单。这个例子中,我们并没有使用对line_items表
的单个列直接映射来建立连接。
belongs_to()方法创建许多管理连接的实例方法。这些方法都是以连接名开头来命名
例如:
item = LineItem.find(2)
# item.product is the associated Product object
puts "Current product is #{item.product.id}"
puts item.product.title
item.product = Product.new(:title => "Advanced Rails",
:description => "...",
:image_url => "http://....jpg",
:price => 34.95,
:date_available => Time.now)
item.save!
puts "New product is #{item.product.id}"
puts item.product.title
如果我们运行它(用一个适当的数据连接),可能会有以下的结果。
Current product is 2
Programming Ruby
New product is 37
Advanced Rails
我们在LIneItem类中使用方法product(),product!=()来存取和更新与product对象
关联的商品项目对象。在背后,Active Record是和数据库的机制是一样的。当我们保存对
应的商品项目时,它自动保存创建的新product。并把新的product的id号和商品项目连接
belongs_to()会把方法添加到使用它的类中。这个描述是基于以下的假定,已定义的
LineItem类属于类Product。
class LineItem < ActiveRecord::Base
belongs_to :product
end
在这个例子中,下面方法将被定义用于商品项目,以及它们属于的products。
1、product(force_reload=false) 返回关联的产品(如果没有关联的产品存在,则返回
nil)。结果被缓存,如果这个定单先前被取出过,则数据库不会再次查询,除非将true做为
一个参数传递给它。
2、product=(obj) 用给出的产品关联这个商品项目,在这个商品项目内设置外键给产品
的主键。如果产品没有被保存,在商品项目被保存时它将被保存,键将在那时被连接。
3、build_product(attributes={}) 构造一个新的product对象,并用给定的属性初始
化它。这个商品项目将被连接给它。Product也不会被保存。
4、create_product(attributes={}) 构建一个新的product对象,连接这个商品项目给
它,然后保存这个product。
has_one() 声明
has_one声明一个给定的类(缺省是混合大小写的属性名字的单数形式)是这个类的子类。
has_one声明和belongs_to一样定义同一个方法集,因此给定类定义例如:
class Order < ActiveRecord::Base
has_one :invoice
end
我们可写成
order = Order.new
invoice = Invoice.new
if invoice.save
order.invoice = invoice
end
你可以通过给has_one传递一个选项的哈希表,来改变Active Record的默认行为。另
外对于:class_name,:foreign_key,和:conditions选项,我们可以看到belongs_to(),我们也可以使用:dependent和: order。
:dependent选项是指子表中的记录行不能独立于对应的父表记录行而单独存在。这就意
味着如果你删除了父类的记录,而且你定义了:dependent=>true的话,Active Record将会自动删除子表中相关的记录行。
: order选项,是决定记录返回之前怎样排序。这似乎有点奇怪。我们在277页的has_many
中还会讨论。
分享到:
相关推荐
python学习资源
jfinal-undertow 用于开发、部署由 jfinal 开发的 web 项目
基于Andorid的音乐播放器项目设计(国外开源)实现源码,主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。
python学习资源
python学习资源
python学习一些项目和资源
【毕业设计】java-springboot+vue家具销售平台实现源码(完整前后端+mysql+说明文档+LunW).zip
HTML+CSS+JavaScarip开发的前端网页源代码
python学习资源
【毕业设计】java-springboot-vue健身房信息管理系统源码(完整前后端+mysql+说明文档+LunW).zip
成绩管理系统C/Go。大学生期末小作业,指针实现,C语言版本(ANSI C)和Go语言版本
1_基于大数据的智能菜品个性化推荐与点餐系统的设计与实现.docx
【毕业设计】java-springboot-vue交流互动平台实现源码(完整前后端+mysql+说明文档+LunW).zip
内容概要:本文主要探讨了在高并发情况下如何设计并优化火车票秒杀系统,确保系统的高性能与稳定性。通过对比分析三种库存管理模式(下单减库存、支付减库存、预扣库存),强调了预扣库存结合本地缓存及远程Redis统一库存的优势,同时介绍了如何利用Nginx的加权轮询策略、MQ消息队列异步处理等方式降低系统压力,保障交易完整性和数据一致性,防止超卖现象。 适用人群:具有一定互联网应用开发经验的研发人员和技术管理人员。 使用场景及目标:适用于电商、票务等行业需要处理大量瞬时并发请求的业务场景。其目标在于通过合理的架构规划,实现在高峰期保持平台的稳定运行,保证用户体验的同时最大化销售额。 其他说明:文中提及的技术细节如Epoll I/O多路复用模型以及分布式系统中的容错措施等内容,对于深入理解大规模并发系统的构建有着重要指导意义。
基于 OpenCV 和 PyTorch 的深度车牌识别
【毕业设计-java】springboot-vue教学资料管理系统实现源码(完整前后端+mysql+说明文档+LunW).zip
此数据集包含有关出租车行程的详细信息,包括乘客人数、行程距离、付款类型、车费金额和行程时长。它可用于各种数据分析和机器学习应用程序,例如票价预测和乘车模式分析。
把代码放到Word中,通过开发工具——Visual Basic——插入模块,粘贴在里在,把在硅基流动中申请的API放到VBA代码中。在Word中,选择一个问题,运行这个DeepSeekV3的宏就可以实现在线问答
【毕业设计】java-springboot+vue机动车号牌管理系统实现源码(完整前后端+mysql+说明文档+LunW).zip
【毕业设计】java-springboot-vue交通管理在线服务系统的开发源码(完整前后端+mysql+说明文档+LunW).zip