iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 10
0
Modern Web

Ruby礦工的Rails地圖系列 第 10

淺談scope -- 常用的條件通通藏在裡面

scope翻為中文是範圍
也可以理解為過濾器

在專案裡時常會為了實現一些商業邏輯,寫下一些很長的ActiveRecord
如果散落在專案內日後會不好管理
所以一般的做法是會整理到model內作為scope
比方說

class Dog < ApplicationRecord
    scope :good, -> {where(status: :good)} 
end

這樣做至少有兩個好處
第一是上面提到的管理方便,如果條件變更時
只需要更改一處即可

第二個好處是增加程式的可讀性
透過scope表達程式本身的意圖
例如

Dog.has_free_time.good.male

直接閱讀,大概就可以猜到
我想要找出所有公的、有空的好狗狗

scope也可以傳遞變數
寫法如下:

scope :where_status, -> (status) {where(status: status)} 
# Dog.where_status("good")

假如說條件相當複雜,或是已經有現成的方法想放到條件當中
當然也是可以的,其實scope本身也就是model的class
所以上面的good scope效果其實與下面這種寫法相同

def self.good
    where(status: :good)
end

另外一種做法,是透過select來傳遞條件
比方說

scope :can_signup, -> { select {|i| i.is_not_full? }}
def is_not_full?
    #code here
end

如此就能將複雜的條件判斷,縮寫成為一個scope
是不是很方便呢?

假如這個條件相當重要
幾乎每一次執行都需要,那可以考慮設為default
例如default_scope order('rank ASC')
這樣就不論在專案的何處,都會預設執行(包含console)

要跳脫default方法如下
Dog.unscoped.where(...)
加上unscoped,後面就可以繼續串接想要的判斷了
是不是很方便呢?


上一篇
How to pass the value from controller to javascript
下一篇
方便的lonely opperate
系列文
Ruby礦工的Rails地圖30

尚未有邦友留言

立即登入留言