Rails开发细节《七》ActiveRecord Associations关联

简介:

Rails开发细节《七》ActiveRecord Associations关联

1.为什么需要关联

很多时候,比如说电子商务中的用户和订单,一个用户会有很多的订单,一个订单只属于一个用户,这就是一种关联。

在创建订单的时候需要用户主键作为外键,删除用户的的同时需要删除用户的订单。

在rails中可以向下面这样订单关联。

 
  1. class Customer < ActiveRecord::Base 
  2.   has_many :orders:dependent => :destroy 
  3. end 
  4.   
  5. class Order < ActiveRecord::Base 
  6.   belongs_to :customer 
  7. end 

就可以像下面这样创建订单,删除用户。

 
  1. @order = @customer.orders.create(:order_date => Time.now) 
  2.  
  3. @customer.destroy 

2.关联的类型

有下面6中关联。

  • belongs_to
  • has_one
  • has_many
  • has_many :through
  • has_one :through
  • has_and_belongs_to_many

 

2.1.belongs_to

belongs_to是一种一对一的关联。表达一种属于的关系。

就像一个订单只能属于个用户。在订单表会有一个字段存储用户主键,这个字段是订单表的外键。

 

 
  1. class Order < ActiveRecord::Base 
  2.   belongs_to :customer 
  3. end 

2.2.has_one

has_one也是一种一对一的关联。表达一种有一个的关系。

就像一个供应商只能有一个账户。账户表有一个供应商主键,是账户表的外键。

 

 
  1. class Supplier < ActiveRecord::Base 
  2.   has_one :account 
  3. end 

2.3.has_many

has_many是一种一对多的关联。表达有多个的关系。

就像一个用户有多个订单。

 

 
  1. class Customer < ActiveRecord::Base 
  2.   has_many :orders 
  3. end 

has_many关联的名称需要使用复数形式。

2.4.has_many :through

has_many是一种多对多的关联。存在一个中间的model。是通过中间model建立关联。

有一个场景就是病人看病,但是需要和医生进行预约。一个医生会有多个预约记录,一个病人也会有多个预约记录。在预约表中会有医生主键和病人主键。

 
  1. class Physician < ActiveRecord::Base 
  2.   has_many :appointments 
  3.   has_many :patients:through => :appointments 
  4. end 
  5.   
  6. class Appointment < ActiveRecord::Base 
  7.   belongs_to :physician 
  8.   belongs_to :patient 
  9. end 
  10.   
  11. class Patient < ActiveRecord::Base 
  12.   has_many :appointments 
  13.   has_many :physicians:through => :appointments 
  14. end 

 

 其实就是把医生和病人的预约关系单独表存放,这张表也会有主键。

 

 
  1. class Document < ActiveRecord::Base 
  2.   has_many :sections 
  3.   has_many :paragraphs:through => :sections 
  4. end 
  5.   
  6. class Section < ActiveRecord::Base 
  7.   belongs_to :document 
  8.   has_many :paragraphs 
  9. end 
  10.   
  11. class Paragraph < ActiveRecord::Base 
  12.   belongs_to :section 
  13. end 

2.5.has_one :through

 

 
  1. class Supplier < ActiveRecord::Base 
  2.   has_one :account 
  3.   has_one :account_history:through => :account 
  4. end 
  5.   
  6. class Account < ActiveRecord::Base 
  7.   belongs_to :supplier 
  8.   has_one :account_history 
  9. end 
  10.   
  11. class AccountHistory < ActiveRecord::Base 
  12.   belongs_to :account 
  13. end 

2.6.has_and_belongs_to_many

has_and_belongs_to_many也是一种多对多的关联。不存在一个中间的model。关系在单独的表中存放,但是这张表没有单独的id,只有双方的id。

 

 
  1. class Assembly < ActiveRecord::Base 
  2.   has_and_belongs_to_many :parts 
  3. end 
  4.   
  5. class Part < ActiveRecord::Base 
  6.   has_and_belongs_to_many :assemblies 
  7. end 

2.7.选择belongs_to还是has_one

belongs_to一般放在有外键的model中,表达一种属于的关系。has_one表达一种拥有的关系。

 

 
  1. class Supplier < ActiveRecord::Base 
  2.   has_one :account 
  3. end 
  4.   
  5. class Account < ActiveRecord::Base 
  6.   belongs_to :supplier 
  7. end 

供应商有一个账号,一个账号属于供应商。

2.8.选择has_many :through还是has_and_belongs_to_many

如果你需要关系model作为独立的实体,就选择has_many :through;不需要独立的实体就选择has_and_belongs_to_many。

 

 
  1. class Assembly < ActiveRecord::Base 
  2.   has_and_belongs_to_many :parts 
  3. end 
  4.   
  5. class Part < ActiveRecord::Base 
  6.   has_and_belongs_to_many :assemblies 
  7. end 

 

 
  1. class Assembly < ActiveRecord::Base 
  2.   has_many :manifests 
  3.   has_many :parts:through => :manifests 
  4. end 
  5.   
  6. class Manifest < ActiveRecord::Base 
  7.   belongs_to :assembly 
  8.   belongs_to :part 
  9. end 
  10.   
  11. class Part < ActiveRecord::Base 
  12.   has_many :manifests 
  13.   has_many :assemblies:through => :manifests 
  14. end 

如果在连接实体上需要验证,回调,或者额外的属性,那就需要使用has_many :through。

2.9.polymorphic

使用polymorphic关联,一个model可以多个model。

就像图片model,既属于员工model,也属于产品model。就是说员工和产品都有图片,他们共享同一个图片model。

 

 
  1. class Picture < ActiveRecord::Base 
  2.   belongs_to :imageable:polymorphic => true 
  3. end 
  4.   
  5. class Employee < ActiveRecord::Base 
  6.   has_many :pictures:as => :imageable 
  7. end 
  8.   
  9. class Product < ActiveRecord::Base 
  10.   has_many :pictures:as => :imageable 
  11. end 

 

 
  1. class CreatePictures < ActiveRecord::Migration 
  2.   def change 
  3.     create_table :pictures do |t| 
  4.       t.string  :name 
  5.       t.integer :imageable_id 
  6.       t.string  :imageable_type 
  7.       t.timestamps 
  8.     end 
  9.   end 
  10. end 

 

 
  1. class CreatePictures < ActiveRecord::Migration 
  2.   def change 
  3.     create_table :pictures do |t| 
  4.       t.string :name 
  5.       t.references :imageable:polymorphic => true 
  6.       t.timestamps 
  7.     end 
  8.   end 
  9. end 

2.10.自连接

有时候,实体会连接自己。

就好比员工表,有些员工同时又是经理,会领导一部分的员工,这样就会造成自连接。

 

 
  1. class Employee < ActiveRecord::Base 
  2.   has_many :subordinates:class_name => "Employee"
  3.     :foreign_key => "manager_id" 
  4.   belongs_to :manager:class_name => "Employee" 
  5. end 

 




本文转自 virusswb 51CTO博客,原文链接:http://blog.51cto.com/virusswb/1019921,如需转载请自行联系原作者

目录
相关文章
|
4月前
|
Web App开发 前端开发 JavaScript
《WASM驱动本地PDF与Excel预览组件的深度实践》
本文围绕前端浏览器端本地文件处理痛点,提出以WASM驱动PDF、Excel等复杂格式文件解析与预览的解决方案。首先剖析传统前端解析方案的性能短板,阐述WASM将底层解析逻辑移植到浏览器的核心价值;接着拆解组件构建关键环节,包括WASM模块与前端的通信设计、文件流本地处理策略、跨格式解析适配逻辑,以及预览渲染层的优化思路;还探讨兼容性适配、内存管理等核心难点,结合实际场景验证方案在加载速度、资源占用上的优势,为前端实现高效、安全的本地文件处理提供了可落地的技术路径。
123 5
|
消息中间件 JavaScript 小程序
SpringBoot 使用线程池如何控制主线程和子线程的事务
SpringBoot 使用线程池如何控制主线程和子线程的事务
|
JavaScript Java 测试技术
基于ssm+vue.js+uniapp小程序的大学生家教兼职管理系统附带文章和源代码部署视频讲解等
基于ssm+vue.js+uniapp小程序的大学生家教兼职管理系统附带文章和源代码部署视频讲解等
252 1
|
存储 SQL 数据库
虚拟化数据恢复—ESXI虚拟机误还原快照的数据恢复案例
虚拟化技术原理是将硬件虚拟化给不同的虚拟机使用,利用虚拟化技术可以在一台物理机上安装多台虚拟机。误操作或者物理机器出现故障都会导致虚拟机不可用,虚拟机中的数据丢失。 虚拟化数据恢复环境: 有一台虚拟机是由物理机迁移到ESXI上面的,迁移完成后为该虚拟机做了一个快照。虚拟机上运行了一个SQL Server数据库,记录了5年左右的数据。 该ESXI上共有二十几台虚拟机,EXSI连接一台某品牌EVA存储,所有的虚拟机(包括故障虚拟机)都存放在该EVA存储上。
|
存储 开发框架 算法
processing像素画教程
本文提供了一个Processing像素画教程,包括创建网格画布、绘制像素、将图片像素化以及调整图片像素化的模糊程度,并通过示例代码展示了如何实现这些效果。
350 1
|
JavaScript
在Vue3+ElementPlus项目中使用具有懒加载的el-tree树形控件
在Vue 3和Element Plus项目中实现具有懒加载功能的el-tree树形控件,以优化大数据量时的页面性能。
2948 0
|
物联网
什么是动态发射功率控制 (DTPC)?
【8月更文挑战第24天】
1651 0
|
数据采集 人工智能 自然语言处理
回望做大模型一年后的感悟
本文为转载,就不计入我的一月更文计划中了。本文作者:刘聪NLP , NLP算法工程师,专业炼丹师。原文链接见:https://mp.weixin.qq.com/s/CfAY8FCrQKKIrQx3U10EcQ
|
前端开发 NoSQL Java
【SpringBoot】秒杀业务:redis+拦截器+自定义注解+验证码简单实现限流
【SpringBoot】秒杀业务:redis+拦截器+自定义注解+验证码简单实现限流
392 0
|
Ubuntu Java Linux
Linux安装ElasticSearch
Linux安装ElasticSearch
458 1