diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 3d23e882566ff3706c6d6713568ac0d7c0d59e4b..c78e602af700dc488ab1d8534b3d7fcd3f224594 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,5 +1,23 @@
## Rails 4.0.0 (unreleased) ##
+* Add CollectionProxy#scope
+
+ This can be used to get a Relation from an association.
+
+ Previously we had a #scoped method, but we're deprecating that for
+ AR::Base, so it doesn't make sense to have it here.
+
+ This was requested by DHH, to facilitate code like this:
+
+ Project.scope.order('created_at DESC').page(current_page).tagged_with(@tag).limit(5).scoping do
+ @topics = @project.topics.scope
+ @todolists = @project.todolists.scope
+ @attachments = @project.attachments.scope
+ @documents = @project.documents.scope
+ end
+
+ *Jon Leighton*
+
* Add `Relation#load`
This method explicitly loads the records and then returns `self`.
diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb
index 65a5044a3d6be2df4b270f02de2d90dbb034701a..3a7a488302afceb06d0323b85274b9773d326ca5 100644
--- a/activerecord/lib/active_record/associations/collection_proxy.rb
+++ b/activerecord/lib/active_record/associations/collection_proxy.rb
@@ -855,7 +855,8 @@ def scoping
@association.scoped.scoping { yield }
end
- def spawn
+ # Returns a Relation object for the records in this association
+ def scope
association = @association
@association.scoped.extending! do
@@ -863,6 +864,9 @@ def spawn
end
end
+ # :nodoc:
+ alias spawn scope
+
# Equivalent to Array#==. Returns +true+ if the two arrays
# contain the same number of elements and if each element is equal
# to the corresponding element in the other array, otherwise returns
diff --git a/activerecord/test/cases/associations_test.rb b/activerecord/test/cases/associations_test.rb
index b7c2bcad004c1b72e8367a58e05e457e2c896d8d..c0f1945cec245201ccec5af35cc5bf2093762dbb 100644
--- a/activerecord/test/cases/associations_test.rb
+++ b/activerecord/test/cases/associations_test.rb
@@ -218,6 +218,13 @@ def test_proxy_association_accessor
def test_scoped_allows_conditions
assert developers(:david).projects.merge!(where: 'foo').where_values.include?('foo')
end
+
+ test "getting a scope from an association" do
+ david = developers(:david)
+
+ assert david.projects.scope.is_a?(ActiveRecord::Relation)
+ assert_equal david.projects, david.projects.scope
+ end
end
class OverridingAssociationsTest < ActiveRecord::TestCase