Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Empty Scope with Ruby on Rails

Following Problem:
I need something like an empty scope. Which means that this scope is emtpy, but responds to all methods a scope usually responds to. I'm currently using a little dirty hack. I simply supply "1=0" as conditions. I find this realy ugly, since it hits the database. Simply returning an empty array won't work, since the result must respond to the scoped methods.

Is there a better existing solution for this or will I need to code this myself?

Maybe some example code could help explain what i need:


class User < ActiveRecord::Base
  named_scope :admins, :conditions => {:admin => true }
  named_scope :none_dirty, :conditions => "1=0" # this scope is always empty

  def none_broken
    []
  end

  def self.sum_score # okay, a bit simple, but a method like this should work!
    total = 0
    self.all.each do |user|
      total += user.score
    end
    return total
  end
end
User.admin.sum_score # the score i want to know
User.none_drity.sum_score # works, but hits the db
User.none_broken.sum_score # ...error, since it doesn't respond to sum_score
like image 248
Baju Avatar asked Sep 17 '10 13:09

Baju


2 Answers

Rails 4 introduces the none scope.

It is to be used in instances where you have a method which returns a relation, but there is a condition in which you do not want the database to be queried.

If you want a scope to return an unaltered scope use all:

No longer will a call to Model.all execute a query immediately and return an array of records. In Rails 4, calls to Model.all is equivalent to now deprecated Model.scoped. This means that more relations can be chained to Model.all and the result will be lazily evaluated.

like image 180
Paul Odeon Avatar answered Sep 17 '22 17:09

Paul Odeon


User.where('false')

returns an ActiveRecord::Relation with zero elements, that is a chain-able scope that won't hit the database until you actually try to access one of its elements. This is similar to PhilT's solution with ('1=0') but a little more elegant.

like image 35
boulder Avatar answered Sep 19 '22 17:09

boulder