Почему не #is_a?работать с экземпляром ActiveRecord :: NamedScope :: Scope - PullRequest
2 голосов
/ 20 октября 2011

Я использую Rails 2.3.9.Чтобы проиллюстрировать проблему, предположим, что у нас есть именованная область действия в модели:

class Book < ActiveRecord::Base
  named_scope :has_isbn, :conditions => 'isbn IS NOT NULL'
end

Если вы получите класс именованной области действия, возвращается ActiveRecord::NamedScope::Scope:

Book.has_isbn.class
# => ActiveRecord::NamedScope::Scope

, если вы используете #is_a? или ===, чтобы выяснить, является ли это областью действия, возвращается false:

Book.has_isbn.is_a?(ActiveRecord::NamedScope::Scope)
# => false
ActiveRecord::NamedScope::Scope === Book.has_isbn
# => false

Кто-нибудь знает, почему это происходит?Вызов именованной области возвращает экземпляр ActiveRecord::NamedScope::Scope (если вы посмотрите на lib/active_record/named_scope.rb в коде Rails, вы увидите, что он вызывает Scope.new и возвращает его), так почему же #is_a? и === не возвращаютtrue

1 Ответ

3 голосов
/ 20 октября 2011

Проверьте этот код из класса Scope:

NON_DELEGATE_METHODS = %w(nil? send object_id class extend find size count sum average maximum minimum paginate first last empty? any? respond_to?).to_set
[].methods.each do |m|
  unless m =~ /^__/ || NON_DELEGATE_METHODS.include?(m.to_s)
    delegate m, :to => :proxy_found
  end
end

Каждый метод в [].methods, то есть каждый метод, на который реагирует массив, определен в экземпляре Scope для передачи в прокси-объект , за исключением методов, определенных массив NON_DELEGATE_METHODS. Они не тронуты, и обратите внимание, что там указан class.

Итак, когда вы звоните scope.class, вы получаете Scope в качестве ответа. Но когда вы вызываете scope.is_a?, вы на самом деле вызываете scope.proxy_found.is_a?, и прокси-объект в этом случае - Array.

>> scope.is_a?(Array)
=> true
...