Rails 4 scope with argument

Rail upgrade 3.2. to Rails 4. I have the following scope:

# 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) } 

But I could not learn how to make the 2nd and 3rd lines. How can I create another scope from the first scope?

+8
ruby-on-rails ruby-on-rails-4
source share
2 answers

Very simple, same lambda with no arguments:

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

or shorter:

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

From Rails Docs

"Rails 4.0 requires applications to use a callable object such as Proc or lambda:"

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


With this in mind, you can easily rewrite the code as such:

 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") } 

If you have many different statuses that you want to maintain, and find it cumbersome, the following might work for you:

 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)} } 
+3
source share

All Articles