【Ruby】每天一點 Rails:find()、find_by()、where()
關於 Rails 中的 find()、find_by()、where()
前提:初學者的學習筆記,僅供參考,敬請指教~
find()
預設只能使用 id 進行查詢,找出單一筆資料。
- 參數:要查找的對象的 ID。
- 如果找到:返回查詢對象。
- 如果沒找到:引發
ActiveRecord::RecordNotFound
例外訊息。
def show
@model = Model.find(params[:id])
# @model = Model.find(1)
end
由於有例外訊息,我們就可以使用 begin...rescue
來捕捉:
def show
begin
@model = Model.find(params[:id])
rescue
redirect_to show_path, notice: "沒有這個 id!"
end
end
find_by()
可設定條件進行查詢,找出符合條件的第一筆資料。
- 參數:物件(key : value)。
- 如果找到:返回查詢對象。
- 如果沒找到:返回 nil 。
def show
@model = Model.find_by(name: params[:name], age: params[:age])
# @model = Model.find_by(name: "Bob", age:24)
end
如果僅使用 id 進行查詢,效果會和 find()
相同:
def show
@model = Model.find_by(id: params[:id])
# 等同於:@model = Model.find(params[:id])
end
由於使用 find_by()
沒找到對象會返回 nil,若我們希望可以像使用 find()
時得到 ActiveRecord::RecordNotFound
,我們可以在 find_by()後面加一個驚嘆號,就可以像find()
捕捉例外訊息。
def show
@model = Model.find_by!(id: params[:id])
end
where()
可設定條件進行查詢,並返回符合條件的所有資料。
- 參數:字串、陣列、物件(key : value)。
- 如果找到:返回
ActiveRecord::Relation
包含一個或多個與參數符合的對象。 - 如果沒找到:會返回一個空的
ActiveRecord::Relation
。
【注意】條件可以是字串、陣列、或是 Hash。但純字串的條件會有 SQL injection 的風險,所以通常會改用陣列處理。
字串
直接將要使用的條件,以字串形式傳入 where 即可:
def show
@model = Model.where("name = 'bob'")
end
然而,如果我們的條件內有變數,字串條件就會有資料庫注入的風險 :
Model.where("name = '%#{params[:name]}%'")
這種情況,應改為陣列方式處理:
def show
@model = Model.where("name= ?", params[:name])
end
Rails 會將 ?
換成 params[:name]
做查詢。條件式後的元素,對應到條件裡的每個 ?
。
來看看官方手冊的提醒:
直接將變數插入條件字串裡,不論變數是什麼,都會直接存到資料庫裡。這表示從惡意使用者傳來的變數,會直接存到資料庫。這麼做是把資料庫放在風險裡不管啊!一旦有人知道,可以隨意將任何字串插入資料庫裡,就可以做任何想做的事。絕對不要直接將變數插入條件字串裡。
陣列
前面已經提到如何使用陣列進行查詢:
def show
@model = Model.where("name= ?", "params[:name]")
end
Were()
可以設下多個條件,使用 AND(&) 連接:
def show
@model = Model.where("name= ? AND age ?", "params[:name]", "params[:age]")
end
上面第一個 ?
會換成 params[:name]
,第二個則會換成 "params[:age]"
。
物件
若使用 key:value
做為查詢的參數,和 find_by()
的使用方式相同。差別在於 find_by()
只會返回符合條件的「第一筆資料」,where 則是會回傳符合條件的「全部資料」。
def show
@model = Model.find_by(name: params[:name], age: params[:age])
# @model = Model.find_by(name: "Bob", age:24)
end
其他查詢方法
Model.all # 找出所有資料
Model.first # 找出第一筆資料
Model.last # 找出最後一筆資料
參考資料: