diff --git a/activerecord/lib/active_record/named_scope.rb b/activerecord/lib/active_record/named_scope.rb index 83043c2..630e080 100644 --- a/activerecord/lib/active_record/named_scope.rb +++ b/activerecord/lib/active_record/named_scope.rb @@ -97,7 +97,28 @@ module ActiveRecord end end end + + # Use this method to create a named \scope that will only return one object rather than a proxy association. + # Singular named \scopes are the same as chaining .first to a named \scope. + # + # class Book + # singular_named_scope :last_read, :order => "last_read DESC", :limit => 1 + # end + # + def singular_named_scope(name, options = {}, &block) + named_scope(name, options, &block) + + (class << self; self end).instance_eval do + define_method "#{name}_with_first" do + instance_eval("#{name}_without_first").first + end + alias_method_chain name, :first + end + end + end + + class Scope attr_reader :proxy_scope, :proxy_options diff --git a/activerecord/test/cases/named_scope_test.rb b/activerecord/test/cases/named_scope_test.rb index 64e8997..e9577ae 100644 --- a/activerecord/test/cases/named_scope_test.rb +++ b/activerecord/test/cases/named_scope_test.rb @@ -277,4 +277,10 @@ class NamedScopeTest < ActiveRecord::TestCase post = Post.find(1) assert_equal post.comments.size, Post.scoped(:joins => join).scoped(:joins => join, :conditions => "posts.id = #{post.id}").size end + + def test_first_argument_should_return_object_not_array + last_read_topic = Topic.first :order => "last_read DESC" + assert_equal last_read_topic, Topic.last_read + end + end diff --git a/activerecord/test/models/topic.rb b/activerecord/test/models/topic.rb index 39ca1bf..f866bfc 100644 --- a/activerecord/test/models/topic.rb +++ b/activerecord/test/models/topic.rb @@ -31,6 +31,7 @@ class Topic < ActiveRecord::Base end named_scope :named_extension, :extend => NamedExtension named_scope :multiple_extensions, :extend => [MultipleExtensionTwo, MultipleExtensionOne] + singular_named_scope :last_read, :order => "last_read DESC", :limit => 1 has_many :replies, :dependent => :destroy, :foreign_key => "parent_id" serialize :content