這個標題、這個圖片,難道是要講什麼吃冰淇淋的感言分享嗎?
但這真的是我第一次接觸這個名詞腦袋中第一個浮現的畫面XD
可能字真的太像了吧(還是只有我這樣覺得?)
看來對我來說,不止中文字有這個問題,好像連英文單字都是...
scope, scoop傻傻分不清楚(誤)
最近做專案常常發現,在撈資料的時候,常常一直點find點where一直點下去,但有發現有時候在同一個controller時,都在對特定Model做同一件事情,在Rails常常可以看到一個字DRY:
Don't Repeat Yourself
為了能夠讓程式碼變得乾淨易讀且方便使用,我們就可以在該controller的Model寫scope
。
也許你會說,可一個一個寫也沒什麼不好啊?
但如果今天需求變更(例如:原本出全部的資料改為撈價格小於100的資料),那不就全站都需要跟著修改?非常不方便,所以這時候我們就需要用到scope
。
先來看個簡單的例子:
#foods_controller.rb
def index
@foods = Food.order(create_at: :desc)
end
撈出所有Food Model的物件並依照建立時間排序,這時候如果要寫成scope來使用,就可以在Model寫:
#food.rb
class Food < ApplicationRecord
scope :show_all, -> { order(create_at: :desc) }
end
這時候的controller就可以這要取用:
#foods_controller.rb
def index
@foods = Food.show_all
end
如果後面的其他action也要做一樣的事情,就只要在Model名稱(此例為Food)後面加你寫 scope 的方法名稱就可以了。
#food.rb
class Food < ApplicationRecord
#寫法一
scope :show_all, -> { order(create_at: :desc) }
#寫法二
def self.show_all
order(create_at: :desc)
end
end
寫法一與寫法二的效果是相同的,至於何時該用哪個,其實就是看個人偏好了,我自己的感覺,如果是條件簡單的話就用scope寫,如果是條件較複雜的話就用類別方法寫。
#food.rb
class Food < ApplicationRecord
scope :cheap_price, ->(price) { where("price < ?", price)}
end
這時候controller就可以拿來用:
#foods_controller.rb
def index
@foods = Food.cheap_price(price)
end
#food.rb
class Food < ApplicationRecord
scope :show_all, -> { order(create_at: :desc).cheap_price(100) }
scope :cheap_price, ->(price) { where("price < ?", price)}
end
#foods_controller.rb
def index
@foods = Food.show_price(price)
end
這樣的寫法就可以撈出價格小於 price 且按照建立時間排序了。
參考資料:
Rails Guide
Ruby on Rails - Scopes
為你自己學Ruby on Rails
“Every challenge, every adversity, contains within it the seeds of opportunity and growth.”
– Roy Bennett, Politician
本文同步發佈於: https://louiswuyj.tw/