当前位置:

首页 > 编程开发 > ruby on rails中Model的关联详解

ruby on rails中Model的关联详解

Rails中Model关联需在两端声明,遵循命名惯例:belongs_to后跟单数,has_many后跟复数。一对多通过外键实现,如妈妈与儿子;多对多借助中间表,如学生与老师通过课程表关联。掌握这些基础可高效处理复杂关联。

在开始学习 Rails 的 Model 关联之前,有几个关键点值得先刻在脑子里:关联关系必须在两端都声明清楚,否则很容易出现让初学者摸不着头脑的错误——而且这对理解代码逻辑也大有裨益。Model 名称用单数,Controller 名称用复数;belongs_to 后面必须是单数且小写,has_many 后面则是复数。这些约定俗成的规则,背后是 Rails 的“惯例优先配置”哲学,理解了它们,后续的代码阅读和编写都会顺畅很多。

ruby on rails中Model的关联详解

一、一对多

举个生活中的例子:王妈妈有两个孩子,小明和小亮。可以说“王妈妈有多个孩子”,也可以说“小明有一个妈妈”“小亮有一个妈妈”。在数据库设计时,我们通常会这样规划:

  • mothers 表:id、name
  • sons 表:id、name

为了建立逻辑关系,需要在“多”的一方(即 sons 表)增加一列作为外键,所以 sons 表实际上有三列:id、name、mother_id(对应 mothers 表的 id)。

如果用原生 SQL 查询,比如找出“小李”的妈妈的名字,你会写:

select test_associate.mothers.name from test_associate.mothers inner join test_associate.sons on sons.mother_id = mothers.id where sons.name = '小李'

换成 Ruby 代码就简洁多了:

class Mother 
  has_many :sons 
end 

class Son 
  belongs_to :mother 
end

逻辑很清楚:一个妈妈有多个孩子,一个儿子属于一个妈妈。在 Rails console 里测试一下:

xiao_wang = Son.first  
mom = xiao_wang.mother

这里的 .mother 方法就是由 class Son 中的 belongs_to :mother 自动生成的。它背后产生的 SQL 相当于:

select * from mothers 
  join sons 
  on sons.mother_id = mothers.id 
  where sons.id = 1

这里有一个细节值得展开:

  • belongs_to :mother 是简写,完整写法是 belongs_to :mother, :class => 'Mother', :foreign_key => 'mother_id'。两者完全等价。
  • Rails 正是通过这种“惯例”来推断:belongs_to :mother 告诉它,mothers 表是“一”的那一端,而当前类 Son 对应 sons 表,外键是 mother_id(默认命名规则)。
  • 因为外键保存在“多”的一端(sons 表),所以 sons 表中必须有一个 mother_id 列。

配置好之后,调用方式非常自然:

son = Son.first
son.mother  # .mother 方法由 belongs_to 产生
mother = Mother.first
mother.sons  # .sons 方法由 has_many 产生

二、一对一

一对一关系相对简单,实际使用频率也不高(比如老公和老婆),这里就不展开介绍了。

三、多对多

再来看一个学生和老师的例子:一个学生有多位老师(学习了多门课程),一个老师也可以教多个学生(一门课程有多个学生来听)。这种情况下,直接把外键放在学生表或老师表里都不合适,需要一张中间表(桥梁表)来记录关联。

表结构设计如下:

  • students 表:id、name
  • teachers 表:id、name
  • lessons 表(中间表):id、name、student_id、teacher_id

对应的原生 SQL 查询,比如找出“小王”的所有老师,可能会写成:

select teachers.*, students.*, lessons.* 
  from lessons, teachers 
  join teachers 
  on lessons.teacher_id = teachers.id 
  join students 
  on lessons.student_id = students.id  
  where students.name = '小王'

而在 Rails 中,只需要在 Model 里声明 has_many :through 即可:

class Student 
  has_many :lessons 
  has_many :teachers, :through => :lessons 
end

注意,has_many :teachers, :through => :lessons 其实等价于 has_many :teachers, :class => 'Teacher', :foreign_key => 'teacher_id', :through => :lessons,但 Rails 的惯例足以推断出这些细节。

同样的,Teacher 类也需要声明关联:

class Teacher 
  has_many :lessons 
  has_many :students, :through => :lessons 
end

这样一来,查询“小王的老师有哪些”就变得极其直观:

Student.find_by_name('小王').teachers

以上就是 Rails 中 Model 关联的几种核心模式。理解这些基础之后,你会发现实际项目中的复杂关联无非是这些基本模式的组合与变种。掌握好它们,后续的代码阅读和数据库设计都会事半功倍。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
作者最新文章
编程开发
相关文章 更多
Ruby日期时间的比较,日期转换等时间日期处理方法大全
Ruby日期时间的比较,日期转换等时间日期处理方法大全

Ruby日期时间处理主要依赖Date、Time和DateTime三个类。Date仅处理日期,Time可处理日期时间,DateTime是Date子类且效率最高。三者支持创建、字符串转换、比较、加减、时区处理及类型互转。Date与DateTime严格校验无效日期,Time则自动进位。常用操作包括构建、解析、格式化及与数值转换。

Ruby信号处理详解
Ruby信号处理详解

Ruby中Process.kill方法发送信号,signal参数可为整数或符号名指定信号类型,pid参数为正数时发送给指定进程,为0时发送给同组所有进程,为负数时发送给对应进程组(绝对值)。

深入分析Ruby 变量
深入分析Ruby 变量

Ruby变量以命名前缀区分五种类型:全局变量($)可跨类访问但副作用大;实例变量(@)为对象私有数据;类变量(@@)在继承链共享;局部变量(小写/下划线)作用域受限;常量(大写)不可重赋值。伪变量如self、nil不可修改。未初始化变量通常为nil,常量赋值会触发警告。

Rails实现字段加密存储
Rails实现字段加密存储

在Rails中,利用ActiveSupport::MessageEncryptor实现字段加密,结合ActiveRecord的serialize机制定义自定义Serializer,使敏感字段存入时自动加密、读取时自动解密,业务层无需关注加密细节。同时需注意密钥安全管理和旧数据的平滑迁移。

ruby中并发并行与全局锁详解
ruby中并发并行与全局锁详解

Ruby全局锁(GIL)使多线程在CPU密集型任务中无法并行提速,但IO操作可并发切换。通过厨师比喻和代码示例,阐释了顺序执行与多线程的差异,强调并发不等于并行。

使用RVM实现控制切换Ruby/Rails版本
使用RVM实现控制切换Ruby/Rails版本

RVM能自由切换Ruby与Rails版本,避免反复重装。通过rvminstall安装指定Ruby版本,用rvmlist查看已安装版本,切换并设为默认。创建gemset绑定Ruby版本,再安装不同Rails版本,即可灵活切换,实现多项目环境隔离。

Ruby 中的 module
Ruby 中的 module

module_function将模块的实例方法复制到单例类,原方法变为私有,仅能通过模块名调用。extendself不改变可见性,public方法既可通过模块名也可通过实例调用。两者均用于暴露模块级方法,但权限不同。

Ruby是什么以及如何使用
Ruby是什么以及如何使用

Ruby是松本行弘于1993年创造的纯面向对象动态语言,融合Smalltalk、Perl和Python精髓,语法简洁易读,一切皆对象。开源解释型跨平台,适合Web开发和脚本编写,可扩展性强,支持多种数据库及GUI工具,是RubyonRails框架的核心语言之一。

Ruby on rails安装后去掉DL is deprecated,please use Fiddle警告信息的方法【测试可用】
Ruby on rails安装后去掉DL is deprecated,please use Fiddle警告信息的方法【测试可用】

在RubyonRails框架中,安装后执行命令时常会出现“DLisdeprecated,pleaseuseFiddle”警告。具体解决方法如下:首先找到Ruby安装目录下的lib/ruby/2.1.0文件夹,进入后找到其中的dl.rb文件,使用文本编辑器打开该文件,定位到含有warn的那一行,在行首添加井号#注释掉该行,保存文件后警告立即消失。

ruby 正则表达式详解及示例代码
ruby 正则表达式详解及示例代码

Ruby正则表达式常用语法包括重复次数(*+?)、范围描述符([])、字符类(如\d\w\s)、边界匹配(^$)、分组捕获及转义等元字符,提供非负整数、邮箱、账号等典型匹配模式,广泛用于表单验证与文本处理,便于快速查阅与套用,功能强大。

查看更多
精品专题 更多
装机必备
装机必备

正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

Windows
Windows

正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

PDF教程
PDF教程

正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

Mac软件 更多
Adobe Acrobat Pro macOS版
Adobe Acrobat Pro macOS版
Mac

Adobe Acrobat Pro 是面向办公、法务、财务、教育及出版用户的专业PDF处理软件,可在Mac上创建、编辑、转换、合并和保护文档,并提供OCR文字识别、表单、批注、内容比较、敏感信息遮盖及电子签名功能。

Blender
Blender
Windows、macOS 和 Linux

Blender 是一款免费开源、跨平台的专业 3D 创作软件,集建模、动画、渲染、视频编辑与视觉合成等功能于一体,广泛应用于影视动画、游戏设计和建筑可视化等领域。软件支持 Cycles 物理渲染器与 Eevee 实时渲染引擎,并提供多边形建模、骨骼绑定、物理模拟等专业工具。Blender 兼容 Windows、macOS 和 Linux 系统,安装包轻巧、运行流畅,依托活跃的全球开发者社区持续更新,是从初学者到专业创作者都值得选择的正版 3D 创作工具。

Shapr3D macOS版
Shapr3D macOS版
Mac

Shapr3D是一款面向工业设计、机械工程、建筑概念和三维打印工作流的CAD软件。Mac版采用Parasolid建模内核,支持草图约束、实体建模、工程图、可视化渲染及常见CAD格式交换,并可通过账户在多台设备之间同步项目。

WINDOWS 更多
AutoCAD Windows版
AutoCAD Windows版
Windows

AutoCAD 是 Autodesk 推出的专业计算机辅助设计软件,Windows 版支持精确二维绘图、三维实体与曲面建模、图纸标注、布局发布和任务自动化,并包含多套行业专业化工具组合,适用于建筑、机械、电气、工程建设及制造设计人员。

Adobe Acrobat Pro Windows版
Adobe Acrobat Pro Windows版
Windows

Adobe Acrobat Pro 是面向专业 PDF 工作的综合解决方案,可在 Windows 中创建、编辑、转换、比较、整理和保护文档,并支持表单、电子签名、扫描件文字识别及敏感信息永久遮盖。订阅还包含网页、移动服务和云端协作能力,

Blender
Blender
Windows、macOS 和 Linux

Blender 是一款免费开源、跨平台的专业 3D 创作软件,集建模、动画、渲染、视频编辑与视觉合成等功能于一体,广泛应用于影视动画、游戏设计和建筑可视化等领域。软件支持 Cycles 物理渲染器与 Eevee 实时渲染引擎,并提供多边形建模、骨骼绑定、物理模拟等专业工具。Blender 兼容 Windows、macOS 和 Linux 系统,安装包轻巧、运行流畅,依托活跃的全球开发者社区持续更新,是从初学者到专业创作者都值得选择的正版 3D 创作工具。