# Ruby(05/14) 五倍紅寶石(第八屆共筆)(2021/8/09)
[Gem套件](https://rubygems.org/?locale=zh-TW)
網址後面通常是 model 的名字
## 資料庫關聯性
- 一對一:belong_to
- 一對多:has_many
- 多對一:
- 多對多:
---
## migration 檔
遷移的意思,只是描述資料表的結構,記錄怎麼變大變小的,描述檔案連續的歷程紀錄 = 資料庫有版控紀錄。
會記錄在 schema.rb 檔案以及 sqlite3 的 schema_ 裏面。
db:migrate 用來掃還沒掃過的資料,每份資料只能被掃一次。
db:rollback 做逆向工程,讓他反向操作。
db:migrate前記得存擋,不然太快做會呈現不出來,如果前面被做過一次就無法在 migrate 第二次。
### 壞掉怎辦:
- 先把方法裡面的東西刪掉,使用 rollback 後再 migrate 一次。
- 大絕招:db:schema:load 根據schema.rb這個檔案,自動載入檔案,跳過錯誤,還原資料庫。
### 撞名
model 名稱不能跟專案名稱、其他 model 或是保留字一樣。
### Object-Relational Mapping(ORM) 物件關係對映
幫助使用者更簡便、安全的去從資料庫讀取資料,透過程式語言,去操作資料庫語言( SQL )。
將關聯式資料庫檔案對映到物件上。
---
## 網路上的刪除不是刪除
有可能只是讓你看不見,但資料其實還在,可透過後台資料庫看到。
---
## Evernote 專案
- title:string => 到資料庫會變成 varchar(1~?)
- content:text => 到資料庫會變成 text(...~4G) 可放較多資料
- deleted:boolean default:false
只會知道有沒有被刪除
- add_index deleted_at:datetime
還會知道刪除時間
### 建索引
類似書籍或字典的目錄,可快速找到需要的資訊。
建索引可加快搜尋資料的速度 => log(n)
常加在不好找的資料上面。
### 語法
- rails c => irb
- Note.all 的all = 類別方法
- command shift F 搜尋關鍵字
- rails routes:看到路徑對照表
路徑取名簡單明瞭即可,ex:/notes
### resources 創造的八條路徑,其中 PATCH 跟 PUT 合併在一起
要背,會由上往下找,對了就執行那個路徑。
- patch:只換掉其中一個資料
- put:整行換掉

### 命名慣例
統一一套規矩,Rails 可以讓每個人用相同邏輯命名,讓大家可用行話,比較好溝通。
- 列表習慣用複數
/members/2/edit
- Resource 資源(有以下可用,總共有8種,可參照上圖):
筆記列表: GET /notes
看 3 號筆記: GET /notes/3
新增筆記:GET /notes/new
編輯 3 號筆記:GET /notes/3/edit
resources :notes, {only: [:index, :show]}, 只開這幾條路的權限
{except 除了...其他都開}
{} hash 可寫可不寫,通常會省略,要看的懂
實作時要先想好要開哪些權限,不要讓使用者自己新增更新等等。
- REST:
一種概念,RESTful API = 軟體建構風格,可參考維基
- 背起來:
- get:取得頁面
- post:寫入資料庫裡面
- put:更新
- delete:刪除
### 增加功能,追加路徑用do end member collection
```rb
resources :notes, only: [:index, :show] do
member do
delete :cancel(概念上:改成 cancel 是取消的意思,不是刪除訂單)
# 刪單一資源(路徑有id數字)
# DELETE /orders/2/cancel
end
collection do
delete :cancel
# 全部資源(沒有id數字)
# DELETE /orders/cancel
end
end
```
### 雜
/notes/:id 的:是字串不是符號
瀏覽器只有支援 get post
其他都是用 post 來表達、模擬的
new 跟 create 是一組的,通常會搭配使用
## 防止灌票
Rails 有預設機制,會檢查 post 行為是不是在我網頁輸入的,不是的話會擋下來。
=> 沒有一樣的 token(令牌、代幣) 送不過來,要帶token過來
- authenrity_token:可以拿到整串 token ,但每次送表單時 Rails 都會產生隨機的 token,所以拿了也沒用。
- 資料庫寫的時區是標準時區 +0 時區
### Routing Error 亂打一通會出現,因為沒有這個路徑
從 Routing Error 可以看到路徑對照表
如果/notes/亂打 ,會出現 show 錯誤是因為後面接的是:id,但他找不到這個 id
用/notes/new 不會出現 show 是因為 Rails 是由上往下找,先找到 new 就不會走到 show 了
- Note.new: 只會在記憶體裡,要用 .save 才能存進去資料庫。
- Note.create: 不用寫 save 可以直接存進去資料庫。

### params
是一個包含用戶所有傳進來的參數的Hash
在 controller 塞 debugger 可以用 params 印出

### 查看有無寫入資料庫
從 sqlite3 的 Browse Data 選你要看的資料表。
### 實作
routes.rb
```rb
Rails.application.routes.draw do
# 創造一個 get "/hello", to: "pages#main" 可以連到/hello頁面
# 名字要對的起來
# get "/notes", to: "notes#index"
# get "/notes/new", to: "notes#new"
# resources 直接生8條路徑,不用像上面一樣一個一個慢慢寫
resources :notes
# 萬一要改網頁路徑名要怎辦?
# 用 path:"articles"可以直接改網頁路徑名,網址從/notes變成/articles
# resources :notes, path:"articles"
end
```
index.html.erb
```rb
<h1> 筆記列表 </h1>
<%# <a href="/notes/new">新增筆記</a>
<%= link_to "新增筆記", "/notes/new" %>
<%# 最推薦寫法,叫做 view helper
全部包在 Ruby 內,link_to 是方法 新增筆記是引數,帶進去讓它顯示名字
new_note_path 也是引數,是要做的事 = 把路徑導向 /notes/new,
亂打一通會顯示 Routing Error,裡面有寫
好處是寫錯會馬上噴錯(NameError) %>
<%# <%= link_to ("新增筆記", new_note_path) %>
<%= link_to "新增筆記", new_note_path %>
<%# 完整路徑 %>
<%# <%= link_to "新增筆記", new_note_url %>
```
new.html.erb
```rb
<h1>新增筆記</h1>
<%# action:往哪送,method: 使用什麼方法,get or post
沒寫就是 get,後端只在乎 name %>
<%# <form action="/notes" method= "POST"></form> %>
<%# 用form_for 快速建立
根據@note的方法名去猜測,會幫你把路徑跟方法跟token都寫好
view 的角色是被動的,不要在這邊 new,controller 負責調度資料,流程控制,
在 controller new 之後再傳過來會比較好 %>
<%= form_for(@note) do %>
<%# name 後面接的名稱要跟後端資料庫建的資料表欄位名稱一樣才能送過去 %>
<%# 資料表欄位名稱如果忘記可以去 db/migrate 裡面的檔案看他的描述 %>
標題:<input type="text" name="title">
內文:<textarea name="content"></textarea>
<input type="submit" value="送出">
<% end %>
<%# QueryString
https://google.com/?p=輸入表格內的東西 & 下一組 %>
```
notes_controller.rb
```rb
class NotesController < ApplicationController
def index
end
def new
# 用 Note.new 做出一個新的 model ,生一個 @note 實體出來,用 @note 才能把值帶到別的檔案
# model 用來放資料庫相關資料,Note 是從 model 來的,裡面有一個 class 叫做 model
# controller 用來產生物件及資料運算,所以@note = Note.new 會放這邊
@note = Note.new
end
def create
# 安插 debugger + 輸入 params 可以印出包含用戶所有傳進來的參數的 hash
# 要印出 hash 可以用 [ ] 裡面放符號或字串都行,
# 為何字串也行是因為 Rails使用到 HashWithIndifferentAccess 這個類別做出來的
# 而我想找出用戶傳進來的內容所以才這樣寫
title = params[:title]
content = params[:content]
# title:、content:是用來對應到資料表名稱,才能取到裡面值,
# 先修教材的 candidate 已經指定好 table 欄位名稱,不用再設定title:、content:
# note 只是一個變數用來代替後面那串
note = Note.new(title: title, content: content)
# 如果存檔成功就把網址轉到/notes
if note.save
redirect_to "/notes"
else
end
end
end
```
---
###### tags: `Ruby` `Rails`