Day-26 : Model 一对一

Model之间的关联,主要分为三个

  1. 一对一:每位使用者(User)可以开一家店(Store)
  2. 一对多:每家店(Store)可以卖很多商品(Product)
  3. 多对多:每家店(Store)除了可以卖很多商品,每个商品也可以在很多店家做贩售

开始先来说明,一对一

建立User Model
https://ithelp.ithome.com.tw/upload/images/20211010/20140259W9qF67Zpti.png

建立Store Model
https://ithelp.ithome.com.tw/upload/images/20211010/20140259i6pvINphLt.png

其中在Store Model内有一个叫做user_id的栏位,为什麽要有他呢?

  1. user_id这栏位的型态是数字,主要对应User Model内的id栏位,又称之为外部键(Foreign Key)
  2. Rails里的惯例是,要被对到的那个Model的名字加上_id
  3. 当然不是加上这些就会有关联

在Model设定关联
https://ithelp.ithome.com.tw/upload/images/20211010/201402597uUYRgK3S1.png

User Model内 写入has_one :store
https://ithelp.ithome.com.tw/upload/images/20211010/20140259Eds0ClZnAE.png

Store Model内 写入belongs_to :user
https://ithelp.ithome.com.tw/upload/images/20211010/20140259sIYgCk4nAr.png


进入rails console
1.用new方法建立一个使用者

user1 = User.new(name:"瓦力")
 => #<User id: nil, name: "瓦力", email: nil, tel: nil, created_at: nil, updated_at: nil>

2.用new方法建立一间商店

store1 = Store.new(title:"良心商店")
 => #<Store id: nil, title: "良心商店", tel: nil, address: nil, user_id: nil, created_at: nil, updated_at: nil>

3.把store1指定给user1

> user1.store = store1
 => #<Store id: nil, title: "良心商店", tel: nil, address: nil, user_id: nil, created_at: nil, updated_at: nil>

4.呼叫save方法:

> user1.save
  TRANSACTION (0.1ms)  begin transaction
  User Create (0.6ms)  INSERT INTO "users" ("name", "created_at", "updated_at") VALUES (?, ?, ?)  [["name", "瓦力"], ["created_at", "2021-10-10 09:46:27.212424"], ["updated_at", "2021-10-10 09:46:27.212424"]]
  Store Create (0.1ms)  INSERT INTO "stores" ("title", "user_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["title", "良心商店"], ["user_id", 1], ["created_at", "2021-10-10 09:46:27.230607"], ["updated_at", "2021-10-10 09:46:27.230607"]]
  TRANSACTION (0.6ms)  commit transaction
 => true
这时候两笔资料都回存在个别的资料表里,并从store1的user_id栏位设定成user1的id

除了上面的个别新增两个物件,在设定关联外,也可以从(User的角度来建立商店)
1.使用new方法来建立User物件

 > user2 = User.new(name:"三眼怪")
 => #<User id: nil, name: "三眼怪", email: nil, tel: nil, created_at: nil, updated_at: nil>

2.使用build_store方法,建立Store物件

> user2.build_store(title:"三眼怪行星")
 => #<Store id: nil, title: "三眼怪行星", tel: nil, address: nil, user_id: nil, created_at: nil, updated_at: nil>

3.呼叫save方法,把两笔资料一起存入资料表中

> user2.save
  TRANSACTION (0.2ms)  begin transaction
  User Create (1.1ms)  INSERT INTO "users" ("name", "created_at", "updated_at") VALUES (?, ?, ?)  [["name", "三眼怪"], ["created_at", "2021-10-10 09:51:10.415498"], ["updated_at", "2021-10-10 09:51:10.415498"]]
  Store Create (0.2ms)  INSERT INTO "stores" ("title", "user_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["title", "三眼怪行星"], ["user_id", 2], ["created_at", "2021-10-10 09:51:10.420409"], ["updated_at", "2021-10-10 09:51:10.420409"]]
  TRANSACTION (0.8ms)  commit transaction
 => true
这样可以看到user_id的资料被设定成为user_2的id,此外,若我们中间有使用build_store换成create_store,则不需要在乎叫save直接从入资料表中罗。

反之,当我们在has_one的Store Model里加上belongs_to方法,Store Model也会多出user跟user=方法,可以直接让我们从Store直接存取User的资料,让我们举个例子:

 > store1 = Store.first
  Store Load (0.4ms)  SELECT "stores".* FROM "stores" ORDER BY "stores"."id" ASC LIMIT ?  [["LIMIT", 1]]
 => #<Store id: 1, title: "良心商店", tel: nil, address: nil, user_id: 1, created_at: "2021-10-10 09:46:27.230607000 +0000", updated_at: ...

因为我们有设定belongs_to :user,所以可以直接用user方法对应这笔资料里的User物件

> store1.user
 User Load (0.3ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
=> #<User id: 1, name: "瓦力", email: nil, tel: nil, created_at: "2021-10-10 09:46:27.212424000 +0000", updated_at: "2021-10-10 09:46:27.212424000 +0000">
仔细看上方,这是一段SQL语法!!!

当我们下了store1.user方法後,这时候Model就会去帮你查,
请问在users这个表格里,有没有id与我这个store1的user_id值是相同的呢?,
一个方法做出所有事,是不是相当方便~完全符合工程师懒惰的性格XDDD

谢谢大家,今天就分享到这儿~

参考资料:为自己学Ruby on Rails


<<:  Day27_是不是跟个资法卯上了~哈哈~CBPR-2021/10/10

>>:  Day25 Redis架构实战-Sentinel选取Replica机制

EP30 - 最後但不是终点

今天是第三十天, 真的要写其实还有很多东西可以写, 但我的确累了, 铁人赛的这三十天像是兼两份差, ...

DAY 14 『 Realm 新增、修改、删除 』Part2

昨天分享如何拉 @IBOutlet、按空白处收回键盘、struct 结构的撰写、Realm 环境安装...

Ubuntu巡航记(4) -- Rust 安装

前言 Rust 是一个现代版的 C/C++ 程序语言,它加入物件导向、套件安装(cargo)、函数式...

Microsoft Azure Pass 学习日志 Day 1

Chap.O Introduce 云端基础 & 简介: Part 1. 云端是什麽,为何要有...

关於取得旧版 macOS 这件事

想要降刷 macOS 版本,或是处理 Fusion Drive,该怎麽办?那里有资源?或是那边有官方...