iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 25
0
自我挑戰組

非本科之30天Ruby / Rails學習筆記系列 第 25

Day25: Rails中的一球冰淇淋 scope

  • 分享至 

  • xImage
  •  

這個標題、這個圖片,難道是要講什麼吃冰淇淋的感言分享嗎?

但這真的是我第一次接觸這個名詞腦袋中第一個浮現的畫面XD
可能字真的太像了吧(還是只有我這樣覺得?)

看來對我來說,不止中文字有這個問題,好像連英文單字都是...

scope, scoop傻傻分不清楚(誤)

Scope

最近做專案常常發現,在撈資料的時候,常常一直點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

scope本身可以帶入scope(串接)

#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/


上一篇
Day24: Rails中的find? find_by? where?
下一篇
Day26: Rails中的view_helper
系列文
非本科之30天Ruby / Rails學習筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言