diff options
author | Pratik Naik <pratiknaik@gmail.com> | 2010-01-18 04:24:24 +0530 |
---|---|---|
committer | Pratik Naik <pratiknaik@gmail.com> | 2010-01-18 04:24:24 +0530 |
commit | 88de6b2de2606e141483ff90323c5f3ec0cfb298 (patch) | |
tree | d29af6f939afa75801753fa42307b5f0589d7b57 /activerecord/lib/active_record/named_scope.rb | |
parent | c6850d8361bbf288cf3adefd087cb9a4bc9c97bc (diff) | |
download | rails-88de6b2de2606e141483ff90323c5f3ec0cfb298.tar.gz rails-88de6b2de2606e141483ff90323c5f3ec0cfb298.tar.bz2 rails-88de6b2de2606e141483ff90323c5f3ec0cfb298.zip |
Inherit named scope class Scope from Relation
Diffstat (limited to 'activerecord/lib/active_record/named_scope.rb')
-rw-r--r-- | activerecord/lib/active_record/named_scope.rb | 118 |
1 files changed, 42 insertions, 76 deletions
diff --git a/activerecord/lib/active_record/named_scope.rb b/activerecord/lib/active_record/named_scope.rb index 9e65fb4ca5..16fde1ffb8 100644 --- a/activerecord/lib/active_record/named_scope.rb +++ b/activerecord/lib/active_record/named_scope.rb @@ -24,7 +24,7 @@ module ActiveRecord # You can define a scope that applies to all finders using ActiveRecord::Base.default_scope. def scoped(options = {}, &block) if options.present? - Scope.new(self, options, &block) + Scope.init(self, options, &block) else current_scoped_methods ? unscoped.merge(current_scoped_methods) : unscoped.spawn end @@ -105,7 +105,7 @@ module ActiveRecord end scopes[name] = lambda do |parent_scope, *args| - Scope.new(parent_scope, case options + Scope.init(parent_scope, case options when Hash, Relation options when Proc @@ -120,117 +120,83 @@ module ActiveRecord end end - class Scope - attr_reader :klass, :proxy_options, :current_scoped_methods_when_defined - NON_DELEGATE_METHODS = %w(nil? send object_id class extend find size count sum average maximum minimum paginate first last empty? any? many? respond_to?).to_set - [].methods.each do |m| - unless m =~ /^__/ || NON_DELEGATE_METHODS.include?(m.to_s) - delegate m, :to => :proxy_found - end - end + class Scope < Relation + attr_accessor :current_scoped_methods_when_defined delegate :scopes, :with_scope, :with_exclusive_scope, :scoped_methods, :scoped, :to => :klass - delegate :new, :build, :all, :to => :relation - def initialize(klass, options, &block) - extend Module.new(&block) if block_given? + def self.init(klass, options, &block) + relation = new(klass, klass.arel_table) - options ||= {} - if options.is_a?(Hash) - Array.wrap(options[:extend]).each {|extension| extend extension } - @proxy_options = options.except(:extend) + scope = if options.is_a?(Hash) + klass.scoped.apply_finder_options(options.except(:extend)) else - @proxy_options = options + options ? klass.scoped.merge(options) : klass.scoped end - unless Scope === klass - @current_scoped_methods_when_defined = klass.send(:current_scoped_methods) - end + relation = relation.merge(scope) - @klass = klass - end + Array.wrap(options[:extend]).each {|extension| relation.send(:extend, extension) } if options.is_a?(Hash) + relation.send(:extend, Module.new(&block)) if block_given? - def reload - load_found; self + relation.current_scoped_methods_when_defined = klass.send(:current_scoped_methods) + relation end - def first(*args) - if args.first.kind_of?(Integer) || (@found && !args.first.kind_of?(Hash)) - proxy_found.first(*args) - else - find(:first, *args) - end - end + def find(*args) + options = args.extract_options! + relation = options.present? ? apply_finder_options(options) : self - def last(*args) - if args.first.kind_of?(Integer) || (@found && !args.first.kind_of?(Hash)) - proxy_found.last(*args) + case args.first + when :first, :last, :all + relation.send(args.first) else - find(:last, *args) + options.present? ? relation.find(*args) : super end end - def size - @found ? @found.length : count - end - - def empty? - @found ? @found.empty? : count.zero? - end - - def respond_to?(method, include_private = false) - super || @klass.respond_to?(method, include_private) - end - - def any? - if block_given? - proxy_found.any? { |*block_args| yield(*block_args) } + def first(*args) + if args.first.kind_of?(Integer) || (loaded? && !args.first.kind_of?(Hash)) + to_a.first(*args) else - !empty? + args.first.present? ? apply_finder_options(args.first).first : super end end - # Returns true if the named scope has more than 1 matching record. - def many? - if block_given? - proxy_found.many? { |*block_args| yield(*block_args) } + def last(*args) + if args.first.kind_of?(Integer) || (loaded? && !args.first.kind_of?(Hash)) + to_a.last(*args) else - size > 1 + args.first.present? ? apply_finder_options(args.first).last : super end end - def relation - @relation ||= begin - if proxy_options.is_a?(Hash) - scoped.apply_finder_options(proxy_options) - else - scoped.merge(proxy_options) - end - end + def count(*args) + options = args.extract_options! + options.present? ? apply_finder_options(options).count(*args) : super end - def proxy_found - @found || load_found + def ==(other) + to_a == other.to_a end private def method_missing(method, *args, &block) - with_scope(relation, :reverse_merge) do - if current_scoped_methods_when_defined && !scoped_methods.include?(current_scoped_methods_when_defined) && !scopes.include?(method) - with_scope current_scoped_methods_when_defined do + if klass.respond_to?(method) + with_scope(self) do + if current_scoped_methods_when_defined && !scoped_methods.include?(current_scoped_methods_when_defined) && !scopes.include?(method) + with_scope(current_scoped_methods_when_defined) { klass.send(method, *args, &block) } + else klass.send(method, *args, &block) end - else - klass.send(method, *args, &block) end + else + super end end - def load_found - @found = find(:all) - end - end + end end |