---
# System prepended metadata

title: 12th 鐵人賽 Day_13 一對多？ ＆ 部落格文章系統
tags: [12th 鐵人賽]

---

---
title: 12th 鐵人賽 Day_13 一對多？ ＆ 部落格文章系統
tags: 12th 鐵人賽
--- 
# 12th 鐵人賽 Day_13 model 一對多？ ＆ 部落格文章系統

嗨！各位朋友大家好，打給後，歹嘎吼，胎尬喉，我是阿圓，一樣有請今天的one piece：![](https://i.imgur.com/FwVEBCX.jpg)
( model 關聯性就像海軍的階級啊！)


#  model 一對多？
部落格接下來要進展到文章的階段了，在此之前，先來講一下 model 關聯性吧。
## 關聯性？
什麼是關聯性， Rails 將model用分層級的方式來連接 model (可以用上司下屬的感覺去聯想)，也就是透過宣告的方式，讓 a model 屬於 b model ，而這樣的方法可以讓在建立資料的時候簡單很多，因為 Rails 會幫你做出好用的方法，以官方文件的例子來說：

若不設立關聯性，在建立一筆屬於顧客的訂單時，必須在建立的時候在指定一個顧客id給他：
```ruby
@order = Order.create(order_date: Time.now, customer_id: @customer.id)
```
若要刪除顧客及他所有的訂單又更麻煩了，要先將訂單都撈出來，一筆一筆刪掉後，再刪顧客：
```ruby
@orders = Order.where(customer_id: @customer.id)
@orders.each do |order|
  order.destroy
end
@customer.destroy
```
使用關聯性：
```ruby=
class Customer < ActiveRecord::Base
  has_many :orders, dependent: :destroy
end
 
class Order < ActiveRecord::Base
  belongs_to :customer
end
```
建立訂單：
```ruby
@order = @customer.orders.create(order_date: Time.now)
```
刪除顧客及他所有的訂單：
```ruby
@customer.destroy
```

而 model 之間彼此的關聯性主要有三種：
1. 一對一 
2. 一對多
3. 多對多

我主要會著重在一對多跟多對多。
## 一對多關聯性
### has_many
用部落格的方式去想，一個admin會有很多的articles
```ruby
class Admin < ActiveRecord::Base
  has_many :articles #盡量是複數喔！
end
```
這樣的話，rails 對於 admin，會生出一些方法可以用：
```ruby=
admin1 = Admin.first
articles1 = Articles.first
#===========#
admin1.articles # 可以列出admin1的所有文章，是一個陣列
admin1.articles = articles1 #把 articles1 這篇文章指定給admin1
#請注意，這樣是把admin1的所有文章砍掉只剩articles1喔，若是要新增，請使用 
admin1.articles << articles1

admin1.articles.build(title:'一對多關聯性')
#用admin1的角度，建立一篇標題為'一對多關聯性的'文章
#要再呼叫save方法才會存入資料庫
admin1.articles.create(title:'一對多關聯性')
#同上，不過不需呼叫save方法
```
### belongs_to

而這些articles會屬於admin。
```ruby=
class Article < ActiveRecord::Base
  belongs_to :admin #盡量是單數喔！
end
```
一樣，對於 article，會生出一些方法可以用於反查：
```ruby=
admin2 = Admin.second
articles2 = Articles.second
#===========#
articles2.admin # 列出 articles2 的作者
articles2.admin = admin2 #把articles2的作者，指定為admin2
```
### 迷思
1. 我在資料的欄位裡面有一個admin_id的欄位就有關聯了嗎？
沒有！資料表是資料表，你只是開了一個欄位給他用，而這個欄位會寫上一個數字，剛好是admin的id，但不代表有關聯性，請去 model 指定關聯性給他們。
3. 設定has_many後，一定要有belongs_to嗎？
不用！如果不需要做到反查的動作，就不需要設定belongs_to

接著讓我們進行部落格實作的部分！


# 部落格實作
## debug

昨天發現一個bug，我current_admin的方法寫錯了，囧"

請聽我娓娓道來：
admin 登入後會有一個發一個`session[:admin_token]`給他，但我沒有讓它存在任何一個欄位裡，根本就找不到這個admin啊！
所以我對admin的資料表多開一個欄位放token，並將sign_in跟current_admin的部份改寫了一下：

```ruby=
# admin_controller
private
def sign_in_admin(admin)
  session[:admin_token] = SecureRandom.uuid
  admin.update(token: session[:admin_token])
end 
```
```ruby=
# application_controller
def current_admin
  @current_admin ||= Admin.find_by(token: session[:admin_token])
end
```
其實也可以使用環境變數寫死，不過這樣在之後上線的時候會需要設定比較多東西～所以我選擇開一個欄位～

### articles
接著我們進行到文章的部分，有些重複的動作我一樣寫概略，這部分會著重在model那邊。
1. 先去routes.rb，指定一下articles的路徑
2. 建立articles_controller 
3. 建立7個action
4. 開始建立model

一樣先來想一下我們的資料裡們會需要有哪些欄位？
1. 標題：string
2. 內文：string
3. admin_id：integer

其中 admin_id 就是為了最上面所說的一對多關聯性，而建立model的時候，可以用`rails g model Article title content admin:references`

用`:references`的話，會自動去model幫你加上`belongs_to :admin`，降低寫錯的機率！

好的，明天我們再來繼續多對多關聯性以及文章分類的部分，感謝各位看到這邊，若有任何建議，請各位不吝指教！我們明天見！
![](https://i.imgur.com/PPbpd2b.gif)

[部落格GitHub](https://github.com/gn2481/yuan_blog)

#### 參考文章
[為你自己學 Ruby on Rails](https://railsbook.tw/chapters/18-model-relationship.html)
[官方文件](https://guides.rubyonrails.org/association_basics.html)