Ruby on Rails 面試題準備

RUBY

、symbols 字串符號 唯一且不會變動的識別名稱 效能比較好,不需要額外的空間來儲存

字串物件(string)每次都會更新記憶體位置,效能不如symbols但優點是有許多方法可以使用如: reverse, size, downcase

二、 問號跟驚嘆號

在 ruby 定義方法時,問號跟驚嘆號也是方法的一部分。

一般使用問號時,慣例上是表示這個方法會回傳布林值 (true 或 false)

使用驚嘆號,通常是表示這個方法可能會有「副作用」或「驚喜」,例如陣列有個叫做 uniq 的方法,它可以產生一個元素不重覆的新陣列。

uniq 方法會回傳一個新的陣列回來,不影響原來的資料

1
2
3
4
5
6
7
original_list = [1,3,4,2,5,2,3]
uniq_list = original_list.uniq

p original_list
[1, 3, 4, 2, 5, 2, 3]
p uniq_list
[1, 3, 4, 2, 5]

但如果你是使用有驚嘆號版本的 uniq! 就不同了,原本的陣列也被改變了。

1
2
3
4
5
6
7
original_list = [1,3,4,2,5,2,3]
uniq_list = original_list.uniq!

p original_list
[1, 3, 4, 2, 5]
p uniq_list
[1, 3, 4, 2, 5]

三、join、split join 用於將陣列( array )中的元素( element )轉成字串( string )。

split 用於將字串( string )轉成陣列( array )

四、module 與 modle

五、namespace

Rails

一、型態 text(文字) 與 string(字串)

text 是一種二進位,binary 的格式。可以放的字非常多,可能幾千、幾萬個字,可以使用在如文章內文

string 能放的字比較少,使用在文字不會太長的情況,例如文章標題

二、什麼是 migration

一種描述資料表該長什麼樣子的描述檔,可以漸進式的去修改你的資料表

優點: 有紀錄,是一連串的檔案,為資料表的演進過程(欄位變化,新增修改刪除) 可以進行版本控制

如果要使 migration 具現化,在終端機下指令:

rails db:migrate

三、CSRF 攻擊

CSRF (Cross-site request forgery),跨站請求偽造。目的不一定是要取得使用者帳戶的控制權或個資,但可以用其他使用者的名義執行某些操作。

這類攻擊的特點是以使用者身份發起

例如,駭客想刪掉某個 Blog 平台的文章,雖然他沒有這個網站的使用權限,但猜到了後台的路徑: /admin/posts/1便可以使用 delete 方法來刪除。接著把這個連結包裝成中獎資訊,寄送給有權限且剛好處於登入狀態的 X 先生,當 X 先生點下連結,文章就會透過 X 先生的權限來刪除了。

這個例子中,CSRF 攻擊之所以可以成功,並不是因為駭客獲取 X 先生 的 cookie 資訊,而是偽裝成是 X 先生。

解決方法:

  1. 檢查 referer 欄位 (可透過檢查 Header 中的 Referer 欄位是否存在及是否為正常流程網域,藉此確認發送端的前一個頁面是否被偽造或合法使用。)
  2. 加入驗證 token (除了驗證 Cookie 的 Token 之外,還需另外在 Request 中放入隱藏的動態 Token 參數。等同於要求每次的 Request 都必須帶上密碼)

四、什麼是 erb 檔 可以在 HTML 裡面寫 ruby 的程式碼。ERb其實可以用來產生任何文字檔格式,例如CSV、XML、JavaScript等等

五、N+1

N+1 指的是 SQL 撈資料時,明明可以一次撈完 (例如要三筆資料),卻使用逐筆撈資料的方式處理 (每次只撈一筆資料) 1次查詢 + N 次的關聯資料查詢就會讓資料庫效能損失

解決方法: 查詢資料的過程中,使用includes多撈一點資料回來。變成 1 + 1

六、中控台模式 rails console

rails c 可在裡面修改資料及查詢資料。 跟 irb 本質上沒有太大差別,中控台模式會把整個 rails 環境,包含相關model 、相關套件整個載下來。

而 irb 就是一般 ruby 環境

七、ORM

Object Relational Mapping

目的: 簡化資料庫操作語法

透過物件的方式,去操作資料表,再換句話說, 把物件導向的語法,透過model,轉換成 SQL 查詢語句,對開發人員來說輕鬆很多。撈回來的資料再交給 model 物件化

例如: Book.all 等同於 select * from books

SQL 可以被 ORM 取代嗎?

  1. 當遇到問題時,比如效能,還是需要在 log (紀錄) 裡看 SQL 的語法,看是否寫錯造成翻譯錯誤。
  2. 複雜的查詢還是必須使用 SQL 語法

ORM 基本操作 CRUD

C new 新增一筆資料 create 新增一筆資料,並寫進資料庫 (寫入失敗時默默 rollback) create! 同上,但寫入失敗時會噴錯誤訊息 (可使用 beging rescure 捕捉) R first 找出第一筆資料 last 找出最後一筆資料 find:找出單一筆資料,且只能透過id去搜尋。找不到時 find 會噴錯誤訊息 (例外訊息) find_by 找出單一筆資料,且可以透過自訂條件去搜尋。找不到時 find_by 會回傳的值是nil find_each 資料量大時,預設每次抓 1000 筆 all 找出所有資料 select(’name’) 同上,但只選取 name 欄位 where(name: ‘Happy’) 找出所有 name 欄位是 Ruby 的資料 order(‘id DESC’) 依照 id 大小反向排序 order(id: :desc) 同上 limit(3) 只取出 3 筆資料 count average sum maximum 與 minimum U update update_all increment 欄位的值 + 1 (沒有存檔功能,要記得 save) toggle 把原本的 true / false 值對調 (沒有存檔功能,要記得 save) D delete destroy 刪的過程中,有一連串的 callback destroy_all

Scope

把商業邏輯寫到 model 裡 取代 controller 一堆 where 是一種類別方法

八、 MVC

MVC 架構 Model View Controller

流程: 一個使用者,透過 route(第一線處理 request 的角色,在 rails 裡非常重要) 導到某一個controller,也許需要調資料(跟model),也許不用。查完之後(如果需要查詢的話)把資料交還給controller,用 view 去做頁面呈現 (HTML & CSS)

Model: 抽象層的概念 model 不是資料表,資料表是 table (實體存在的東西)

Controller: 本身是一個 class , 一個一個的 action 就是方法

View: 在 controller acton (透過 model 向資料庫) 拿到的 raw data,搭配畫面跟表單,組成一般使用者可以讀的表格、表單

優點∶ 歸類整齊,易於前後端分工 流程控制: controller 資料邏輯: model 畫面相關: view

View 技術上來說,其實是會回傳 HTML 內容的方法(method、function)

九、資料驗證 前端驗證: 還沒送出去前,在表單用 JavaScript擋下來,缺點驗證是容易被避開 後端驗證: 寫進資料庫之前,如果內容沒填、格式有問題等,把它擋下來。

model 層,比如名字欄位必填,可以使用以下的驗證器

1
validates :name, presence: true

其他在 rails guide 的 Validation Helpers 還有更多可以使用的驗證

不寫在 controller 的原因,每一個 controller 要寫去都要做檢查

model 是整包做檢查

若同時有不同系統存取資料庫的狀況(比如PHP),則無法保證資料一定無誤。這時可以在資料庫本體擋掉,比較安全

如何繞過驗證 c.save(validate: false)

十、 Callback

資料存檔的流程會經過以下流程: save > valid > before_validation > validate > after_validate > before_save > before_create > create > after_create > after_save > after_commit

before_save 資料寫進跟更新都會執行 before_create 資料被建立的時候才會執行

十一、 Active Record

是一種設計模式,本身是一個物件。 每一筆資料包裝成一個物件,並在其增加資料操作邏輯,讓資料的存取更便利

這個物件,由欄位、基本操作、商業邏輯組成

我們可以說 MVC 裡的 Model = 依照 Active Record 模式設計的產物

而 Active Record 是一種 ORM 框架

Active Record ORM Model Database Table

十二、二大哲學

(一) 慣例優於設定 Convention Over Configuration(CoC) 慣例 = 可以少寫不必要的程式碼 學習 Rails ,等於是在學習 Rails 的慣例 例如:

  1. Model: 大寫、單數
  2. Table: 小寫、複數
  3. 每個表格預設會有一個叫做 id 的流水編號欄位
  4. 在 migration 裡預設會有個 timestamps,在具現化的時候,會轉換成 created_at updated_at這兩個時間欄位,在資料新增或更新的時候自動寫當下時間
  5. model 跟 table 的對應 pluralize 找出複數名詞的方法 singularize 找出單數名詞的方法 比如
"person".pluralize
=> "people" 
"people".singularize
=> "person" 

若需自定義,在config/initializers/inflections.rb設定

  1. 檔案跟 model 的對應。類別名稱由兩個以上的單字組成時,Model 名稱應要遵循 Ruby 的命名慣例,採用駝峰式命名,而資料表名稱必須採用底線分隔。 underscore變成蛇式的方法 camlize變成駝峰式 比如
"HappyHour".underscore
=> "happy_hour"
"happy_hour".camlize
=> "HappyHour"  
  1. 外鍵 - 應用資料表的單數形加上 _id 來命名,比如 item_id, order_id。Active Record 會在你建立 Model 之間的關聯時,尋找這種形式的欄位 singularized_table_name_id。

當 model 之間的關連不是用慣例時,必須加上 foreign_key

比如有一個 store 的 model:

1
belongs_to :owner #foreign_key: 'owner_id'

foreign_key 是遵循慣例,所以後面可以省略,但如果是接手別人案子或設計,可能原本不是用 ruby 或 rails 寫的,則需寫出 foreign_key 如下

1
belongs_to :owner foreign_key: 'u_id'
  1. 主鍵(流水編號欄位id) - Active Record 預設會使用一個叫做 id 的整數欄位,作為資料表的主鍵。採用 Active Record migration 來建立資料表時,這個欄位會自動產生。

  2. 參照值

user:references 會造出 user_id 這個數字型態欄位 會指向 user 這個 model 的主鍵(流水編號欄位id)

(二) Don’t repeat yourself

十三、關聯性

一對一、一對多、多對多 has_one 不是設定,它是一個類別方法,例子中的 store 是它的參數 執行 has_one 後,會動態做出四個方法,比如

1
2
3
4
5
6
7
has_one :store

#做出以下的方法
#store
#store=
#build_store(不會直接寫進資料庫)
#create_store 
1
2
3
4
5
belongs_to :owner

#做出以下的方法
#owner
#owner=
1
2
3
4
5
6
7
has_many :books

#做出以下的方法
#books
#books=
#build
#create

十四、 include、extend、reuqire、load

include:include是用於向類中包含模組的關鍵字。它將指定的模組中的方法添加到類的實例中,使其可以調用模組中的方法。

extend:extend也是用於向類中包含模組的關鍵字,但是它將指定的模組中的方法添加到類本身中,使得該類可以調用模組中的方法。

require:require是用於加載其他 Ruby 文件中的程式碼。它可以將其他文件中的類、方法和變量加載到當前文件中。如果該文件已經加載過了,require將不會再次加載。

load:load也是用於加載其他 Ruby 文件中的程式碼。它和require的區別在於,load每次都會重新加載指定的文件,即使該文件已經加載過了。

include vs extend

十五、API

十六、RESTful

十七、CACHE 暫存

十八、 Active Job 背景工作

十九、 前端的 partial 和 helper 差別

二十、Gemfile 的用意?

二十一、 namespace

updatedupdated2023-03-042023-03-04