# Ruby(06/14) 五倍紅寶石(第八屆共筆)(2021/8/10) ## TDD:(很重要!) 測試驅動開發,重點是開發 - 功能: 寫程式確認另一段 code 能否正常運作,因為重複的東西用機器來做可以自動化且省時間 - 用法: 先規劃好,畫好藍圖,再實做內容 先寫測試再寫程式,測試不存在的功能,假設他能正常運作 先把結果(規格)寫出來,確定是壞的再修正,如果遇到錯誤就一個一個修正,不要期待一開始就會是對的 - 結構: 整體簡單清楚易懂就好,不要用複雜的語法 - why? - 本身是規格 - 做出比較好的設計 - 可以重構 - 更有信心的程式碼 - why 不寫? - 沒時間:大專案反而會節省時間 - 跑測試太慢:會慢一點點,但可自動幫你抓bug,好處 > 壞處 - 很脆弱:只能怪自己改不動 - 不會寫:學著寫,練習從結果推回去 - 面試題: - 怎麼測不存在的東西? 假設他存在 - 要測什麼? 看需求 ### 測試套件 - minitest:執行快 - RSpec(Ruby Specification):Ruby 規格,主流套件,要額外安裝,執行慢,語法易懂 ### 參考書 - The Pragmatic Pookshelf 書局 - Programming Ruby - Rails 5 Test Prescription (處方籤) - RSpec3! - Everyday Rails Testing with RSpec! - OREILLY --- ## Rails evernote ### 資料清洗 - .any?:有沒有東西 - .errors.any?:有沒有錯誤 - .errors.full_message:錯誤訊息 ### SCSS SASS 超級 CSS,比一般 CSS 更好用 ### 實做 notes_controller.rb ```rb class NotesController < ApplicationController # GET 顯示所有資料 def index # @notes = Note.all # 排序交給資料庫做 :desc做反向排列 # 不要做 Note.all.sort.reverse # 可寫 all 可不寫,當你沒有要做其他事就寫 all @notes = Note.order(id: :desc) end # GET 到新頁面建立資料 def new @note = Note.new end # POST 寫入資料庫 def create # title = params[:title] # content = params[:content] # 用 note 去包就不用像上面一樣手動控制一個一個寫入,但要經過清洗 # 清洗資料 Strong Parameter:防止別人亂寫東西進來,可過濾掉不要的欄位, # require輸入資料 permit欄位 clean_note = params.require(:note).permit(:title, :content) # title: 是用來對應到資料表名稱 # @note 只是一個變數用來代替後面那串 @note = Note.new(clean_note) # 如果存檔成功就把網址轉到/notes if @note.save redirect_to "/notes" else # 借views/notes/new.html.erb來畫出來給你看,不是重新讀取 new # render 過程發現 @note 不是原本空空的 @note ,而是有帶了(clean_note)參數, # 他會連同參數裡面的東西一起拿過來 # form_for 會再幫你塞回原本欄位,保留下來 render :new end end # GET 顯示單一資料 def show # 有要傳到其他方法或 view 就用實體變數 # find 找不到會噴錯 ActiveRecord::..... # find_by 只會噴 nil # 太複雜才會用SQL語法操作,避免 SQL injection @note = Note.find(params[:id]) end end ``` new.html.erb ```rb <%# 用form_for 快速建立 根據@note的方法名去猜測,會幫你把路徑跟方法跟token都寫好 view 的角色是被動的,不要在這邊 new,controller 負責調度資料,流程控制, 在 controller new 之後再傳過來會比較好 %> <%#form 小幫手%> <%# 餵進來的東西如果有料會自動幫你帶入 %> <%= form_for(@note) do |f|%> <%= f.label :title, "標題" %> <%= f.text_field :title %> <%= f.label :content, "內文" %> <%= f.text_area :content %> <%= f.submit "送出" %> <% end %> ``` show.html.erb ```rb <h1>筆記: <%= @note.title %> </h1> <p><%= @note.content %></p> ``` index.html.erb ```rb <%# 最推薦寫法,叫做 view helper 全部包在 Ruby 內,link_to 是方法 新增筆記是引數,帶進去讓它顯示名字 new_note_path 也是引數,是要做的事 = 把路徑導向 /notes/new,亂打一通會顯示 Routing Error,裡面有寫 好處是寫錯會馬上噴錯(NameError) %> <%# <%= link_to ("新增筆記", new_note_path) %> <%= link_to "新增筆記", new_note_path %> <%# 有加=會被印出 %> <ul> <%# 從index方法來的,@notes 是陣列因為是物件所以可以用方法 %> <% @notes.each do |note| %> <%#link_to note.title, note_path(note.id)%> <%# link_to(note.title) ,link_to是方法,note.title是參數 %> <%# link_to 呈現的資料,路徑:note_path跟id可不寫 %> <li><%= link_to note.title, note_path(note) %></li> <% end%> </ul> ``` note.rb ```rb class Note < ApplicationRecord # 驗證交給model # 有東西才給過 # validates = 類別方法 2 個參數,第二個是 hash validates :title, presence: true validates :content, presence: true end ``` form.scss ```scss // application.css 內不建議用 require_tree .,會按照英文字母順序載入,可能會被蓋掉 // require_tree . 可以把這個目錄的檔案都包起來 // require_self 寫在自己那邊也可 // application.css 入口打包擋 .field_with_errors { display: inline-block; label { color: red; } input[type="text"], textarea { border: 1px solid red; } } ``` --- [Rails XMind](https://www.xmind.net/m/E4xCGw) --- ###### tags: `Ruby` `Rails`