2014-05-01 47 views
8

升級Rails 3.2。到Rails 4.我有以下範圍:帶有參數的Rails 4作用域

# Rails 3.2 
scope :by_post_status, lambda { |post_status| where("post_status = ?", post_status) } 
scope :published, by_post_status("public") 
scope :draft, by_post_status("draft") 

# Rails 4.1.0 
scope :by_post_status, -> (post_status) { where('post_status = ?', post_status) } 

但我找不出如何做第二和第三行。我如何從第一個範圍創建另一個範圍?

回答

17

非常簡單,只需同樣的拉姆達不帶參數:

scope :by_post_status, -> (post_status) { where('post_status = ?', post_status) } 
scope :published, -> { by_post_status("public") } 
scope :draft, -> { by_post_status("draft") } 

或多個短路:

%i[published draft].each do |type| 
    scope type, -> { by_post_status(type.to_s) } 
end 
3

Rails edge docs

「的Rails 4.0要求範圍使用可調用對象,如Proc或lambda:「

scope :active, where(active: true) 

# becomes 
scope :active, -> { where active: true } 


考慮到這一點,你可以很容易地重寫你的代碼是這樣的:

scope :by_post_status, lambda { |post_status| where('post_status = ?', post_status) } 
scope :published, lambda { by_post_status("public") } 
scope :draft, lambda { by_post_status("draft") } 

倘若你有你想支持和發現許多不同的狀態這很麻煩,以下可能適合你:

post_statuses = %I[public draft private published ...] 
scope :by_post_status, -> (post_status) { where('post_status = ?', post_status) } 

post_statuses.each {|s| scope s, -> {by_post_status(s.to_s)} } 
+0

那麼什麼是方法和範圍的區別。我的意思是,如果你想例如限制用戶的數量,你可以通過方法或範圍來做到,對吧?在這種情況下使用範圍而不是方法是否是最佳做法? –