Empty Scope with Ruby on Rails

时间秒杀一切 提交于 2019-12-10 12:30:38

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!