diff --git a/activerecord/lib/active_record/named_scope.rb b/activerecord/lib/active_record/named_scope.rb index 120ec88..9aae49c 100644 --- a/activerecord/lib/active_record/named_scope.rb +++ b/activerecord/lib/active_record/named_scope.rb @@ -11,7 +11,7 @@ module ActiveRecord def self.included(base) base.class_eval do extend ClassMethods - named_scope :all + named_scope :all, {} named_scope :scoped, lambda { |scope| scope } end end @@ -72,9 +72,17 @@ module ActiveRecord # end # end # - def named_scope(name, options = {}, &block) + def named_scope(name, options = nil, &block) scopes[name] = lambda do |parent_scope, *args| Scope.new(parent_scope, case options + when nil + scope_name = "scope_#{name}" + raise(NoMethodError, "#{parent_scope} must support #{scope_name}") unless parent_scope.respond_to?(scope_name) + parent_scope.send(scope_name, *args) + when Symbol + scope_name = options + raise(NoMethodError, 'hello darling') unless parent_scope.respond_to?(scope_name) + parent_scope.send(scope_name, *args) when Hash options when Proc diff --git a/activerecord/test/cases/named_scope_test.rb b/activerecord/test/cases/named_scope_test.rb index 3d3cecd..a6c6a3f 100644 --- a/activerecord/test/cases/named_scope_test.rb +++ b/activerecord/test/cases/named_scope_test.rb @@ -77,6 +77,43 @@ class NamedScopeTest < ActiveRecord::TestCase assert_equal topics_written_before_the_second, Topic.written_before(topics(:second).written_on) end + def test_class_method_scopes_with_optional_args + topics_written_before_the_third = Topic.find(:all, :conditions => ['written_on < ?', topics(:third).written_on]) + first_topics_written_before_the_third = Topic.find(:all, + :conditions => ['written_on < ?', topics(:third).written_on], + :order => 'written_on DESC', + :limit => 1 + ) + assert_raise ArgumentError, 'Initial argument should not be optional' do + Topic.written_before_with_options + end + assert_equal topics_written_before_the_third, Topic.written_before_with_options(topics(:third).written_on) + assert_equal first_topics_written_before_the_third, Topic.written_before_with_options(topics(:third).written_on, { :limit => 1, :order => 'written_on DESC' }) + end + + def test_class_method_scopes_with_custom_method_name + topics_written_before_the_third = Topic.find(:all, :conditions => ['written_on < ?', topics(:third).written_on]) + first_topics_written_before_the_third = Topic.find(:all, + :conditions => ['written_on < ?', topics(:third).written_on], + :order => 'written_on DESC', + :limit => 1 + ) + assert_raise ArgumentError, 'Initial argument should not be optional' do + Topic.custom_scope_name + end + assert_equal topics_written_before_the_third, Topic.custom_scope_name(topics(:third).written_on) + assert_equal first_topics_written_before_the_third, Topic.custom_scope_name(topics(:third).written_on, { :limit => 1, :order => 'written_on DESC' }) + end + + def test_class_method_not_available + assert_raise NoMethodError, 'Should raise NoMethodError when parent scope does not support scope method' do + Topic.scope_method_not_implemented + end + assert_raise NoMethodError, 'Should raise NoMethodError when parent scope does not support scope method' do + Topic.custom_scope_method_not_implemented + end + end + def test_extensions assert_equal 1, Topic.anonymous_extension.one assert_equal 2, Topic.named_extension.two diff --git a/activerecord/test/models/topic.rb b/activerecord/test/models/topic.rb index d2503b7..0192183 100755 --- a/activerecord/test/models/topic.rb +++ b/activerecord/test/models/topic.rb @@ -4,7 +4,7 @@ class Topic < ActiveRecord::Base } named_scope :approved, :conditions => {:approved => true} named_scope :replied, :conditions => ['replies_count > 0'] - named_scope :anonymous_extension do + named_scope :anonymous_extension, {} do def one 1 end @@ -27,6 +27,16 @@ class Topic < ActiveRecord::Base named_scope :named_extension, :extend => NamedExtension named_scope :multiple_extensions, :extend => [MultipleExtensionTwo, MultipleExtensionOne] + named_scope :written_before_with_options + def self.scope_written_before_with_options time, *args + options = args.extract_options! + options.merge(:conditions => [ 'written_on < ?', time ]) + end + named_scope :custom_scope_name, :scope_written_before_with_options + + named_scope :scope_method_not_implemented + named_scope :custom_scope_method_not_implemented, :no_such_method + has_many :replies, :dependent => :destroy, :foreign_key => "parent_id" serialize :content