I’m using Rails 2.3.9. To illustrate the issue, suppose we have a named scope on a model:
class Book < ActiveRecord::Base
named_scope :has_isbn, :conditions => 'isbn IS NOT NULL'
end
If you get the class of the named scope, ActiveRecord::NamedScope::Scope is returned:
Book.has_isbn.class
# => ActiveRecord::NamedScope::Scope
However, if you use #is_a? or === to figure out whether it is a scope, it returns false:
Book.has_isbn.is_a?(ActiveRecord::NamedScope::Scope)
# => false
ActiveRecord::NamedScope::Scope === Book.has_isbn
# => false
Does anyone know why this is happening? Calling a named scope returns an instance of ActiveRecord::NamedScope::Scope (if you look at lib/active_record/named_scope.rb in the Rails code, you can see it calls Scope.new and returns it), so why doesn’t #is_a? and === return true?
Check out this code from the
Scopeclass:Every method in
[].methods–that is, every method an array responds to–is defined on theScopeinstance to pass through to the proxy object, except for the methods defined in theNON_DELEGATE_METHODSarray. These are untouched, and notice thatclassis listed in there.So, when you call
scope.class, you getScopeas the response. But when you callscope.is_a?, you’re actually callingscope.proxy_found.is_a?, and the proxy object in this case is anArray.