问题
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
回答1:
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.
回答2:
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.
回答3:
Sorry User.scoped
is not what you want. As commented this returns everything. Should have paid more attention to the question.
I've seen where('1 = 0')
suggested before and Rails should probably cache it as well.
Also, where('1 = 0')
won't hit the database until you do .all
, .each
, or one of the calculations methods.
回答4:
I thing you need User.scoped({})
回答5:
How about User.where(id: nil)
?
Or User.where(_id: nil)
for mongoid.
回答6:
The thing you are looking for does not exist. You could implement something like this by monky patching the find
method. Yet, this would be an overkill, so I recomend keeping this unless it's performance critical.
回答7:
Looking at your example code indicates you may not know about aggregated queries in SQL which are exposed as calculations methods in Rails:
User.sum(:score)
will give you the sum of all users' scores
Take a look at Rails Guides for more info:
http://guides.rubyonrails.org/active_record_querying.html#sum
来源:https://stackoverflow.com/questions/3735838/empty-scope-with-ruby-on-rails