Skip to main content

建立 ruby 專案

可以在 new 前面加上版本號,那這個專案就會是使用這個版本,而在專案名稱後面加上參數,就可以幫你在建立專案的時候,順便把 Webpacker 相關的套件以及設定一次搞定

rails _6.1.4.6_ new ruby-demo --webpack

開啟 rails 的環境

rails sever

什麼是 mvc ?

Rails 專案是採用 Model、View、Controller(簡稱 MVC)的方式設計的。MVC 的特性讓專案在開發的過程中,各個模組權責分離,也較好維護或調整

  • Model:掌管資料,但 本身並不是資料庫 使用 ORM (Object Relationship Mapping)轉譯 SQL 跟資料庫溝通拿資料

  • Controller:就像是櫃檯,來處理接收到的訊息請 View 或是 Model 工作,算是滿重要的中控流程中心

  • View:負責資料顯示,往往是 user 看到的畫面,可以是網頁、手機應用程式的介面,或者其他 user 互動的形式。它只是將 Model 中的資料呈現給 user,並接收來自 user 的輸入

快速生成 rails 網頁

在 rails 中,scaffold 是生成器命令,用於一次性生成一個完整的 CRUD(Create, Read, Update, Delete)模型

以下是 scaffold 命令的基本用法:

rails generate scaffold User name:string email:string tel:string

可以簡略成:

rails g scaffold User name email tel

除了 generate 可以省略之外,因為 string 是常見的型別,所以也可省略

再新創第二個 model:

rails g scaffold Post title content:text is_availible:boolean user:references

這裡的 user:references 等於 user_id:integer,這樣的語法是為了建立『 關聯 』,user:references 會自動在 post 模型中建立 bolongs_to:user 的關聯,這樣就可以在 post 模型中直接連結 user 模型(例如:post.user)

什麼是 migrate ?

用來描述資料表,當你需要新增、刪除或修改數據庫表格的結構時,會使用到 migrate,而 rails db:migrate 是一個 Rails 的命令,可以讓資料表具現化出來

  • 描述資料表
  • 歷史紀錄(版本控制)

下拉選單(collection_select)

 <%= form.collection_select(:user_id, User.all, :id, :name) %>

N+1 問題

拿 post 當例子,在這個頁面裡,每新增一筆資料,就會撈一次資料,這樣子會產生額外的效能問題

新增三筆資料,但卻跑了四次

Post Load (0.2ms)  SELECT "posts".* FROM "posts"
↳ app/views/posts/index.html.erb:17
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
↳ app/views/posts/index.html.erb:22
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]
↳ app/views/posts/index.html.erb:22
CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]

includes 是 Rails ActiveRecord 中的一個方法,用於在檢索數據時預先載入關聯記錄,以避免 N+1 查詢問題

解決辦法:在 post_controller.rb 裡,

def index
@posts = Post.all.includes(:user)
end

回到終端機查看,這樣一來,就可以解決效能上的問題,一口氣把所有資料都撈出來

Post Load (0.3ms)  SELECT "posts".* FROM "posts"
↳ app/views/posts/index.html.erb:17
User Load (0.8ms) SELECT "users".* FROM "users" WHERE "users"."id" IN (?, ?) [["id", 1], ["id", 2]]