我们切换到新的分支进行开发
git checkout -b class_name_and_source
补充,前面多对多本质也是两个1对多。而1对多关系只需要属于多的那张表添加外键即可,如用户和微博是1对多,微博属于多的那方,所以只需要posts表添加UserID这个外键,users表不用修改表结构。而前面多对多中多的是中间表那方,所以中间表保存两个外键,其他表的表结构不用修改。
一言概之:
class_name只会出现在下面两种情况(第二种情况还必须用source):
1、给1对多起别名
2、给多对多起别名
source只会出现在下面两种情况(第二种情况加不加source都可以):
1、has_many+through+给多对多关联起别名(:class_name)
2、has_many+through
class_name
class_name给1对多关系起别名
创建模型文件,我们这回就不考虑前后端分离自定义表名的情况,所以就不写迁移文件,直接使用生成模型的命名(会生成一些我们这里不用的测试文件)
rails g model User name:string age:integer
rails g model Post title:string content:string UserID:integer
rake db:migrate
-
创建种子数据
rake db:seed
然后我们在数据库就可以看到生成的种子数据了
-
修改模型文件
上面就已经完成了模型关联,上面就是最常见的方式。我们可以使用user.posts获取该用户下的所有微博。
如果我们希望user.weibos也能获取到该用户下的所有微博呢(也就是给关联起别名)?
这就是class_name的使用场景。
使用了别名class_name之后,就不能继续使用user.posts这样的方式了
我们还可以把post.user修改为post.yonghu的方式
起别名只是名称修改,单复数还是和原来默认的一样,has_many后面是别名复数,belongs_to后面是别名单数
给多对多起别名,class_name+source
给多对多起别名,就是给中间表的两个1对多起别名。因为中间表保存两个表的外键,class_name指明了要关联的模型名,source则指明用中间表的哪个外键去关联到该模型,不然会报错。
用法如下:
如果不加source会报错如下:
product.lou_cengs
ActiveRecord::HasManyThroughSourceAssociationNotFoundError:
Could not find the source association(s) "lou_ceng" or :lou_cengs in model ActivityFloorProduct.
Try 'has_many :lou_cengs, :through => :activity_floor_products, :source => <name>'.
Is it one of activity_floor or product?
给另外一个模型起别名:
错误示例
既然多对多关联通过中间表起别名有两个表可以指定关联,那么需要使用source指明关联哪张表-----source的值应该就是class_name模型对应的表名单数。
分析如下:在楼层模型里面,source正确的情况下是:product,用中间表的ProductID去关联class_name对应的products表,所以第一条sql是正确的,ON `products`.`ID` = `activity_floor_products`.`ProductID`
而source: :activity_floor则是
ON `products`.`ID` = `activity_floor_products`.`ActivityFloorID`
正确:
SELECT `products`.* FROM `products` INNER JOIN `activity_floor_products` ON `products`.`ID` = `activity_floor_products`.`ProductID` WHERE `activity_floor_products`.`ActivityFloorID` = 'floor01'
错误:
SELECT `products`.* FROM `products` INNER JOIN `activity_floor_products` ON `products`.`ID` = `activity_floor_products`.`ActivityFloorID` WHERE `activity_floor_products`.`ActivityFloorID` = 'floor01'
提交到git仓库
进入项目根目录
.../active_record_second# git init
Initialized empty Git repository in /home/**********/active_record_second/.git/
git add -A
git commit -m "(02)种子数据,给关联起别名,class_name和source"
提交
git push -u https://github.com/xiaohuacc/active_record_second.git class_name_and_source