diff options
author | Jon Leighton <j@jonathanleighton.com> | 2011-04-18 23:35:22 +0100 |
---|---|---|
committer | Jon Leighton <j@jonathanleighton.com> | 2011-04-18 23:35:22 +0100 |
commit | 019cd51a3f36ec7631bf1b63c069e62a3b5185d4 (patch) | |
tree | 6bdb235ccdd5389b381e129fdeef3582db71175e /activerecord | |
parent | 6f84c73dc48538202766cff3d973a53d3c30848e (diff) | |
download | rails-019cd51a3f36ec7631bf1b63c069e62a3b5185d4.tar.gz rails-019cd51a3f36ec7631bf1b63c069e62a3b5185d4.tar.bz2 rails-019cd51a3f36ec7631bf1b63c069e62a3b5185d4.zip |
Bring back support for passing a callable object to the default_scope macro. You can also just use a block.
Diffstat (limited to 'activerecord')
-rw-r--r-- | activerecord/CHANGELOG | 11 | ||||
-rw-r--r-- | activerecord/lib/active_record/base.rb | 12 | ||||
-rw-r--r-- | activerecord/test/cases/relation_scoping_test.rb | 12 | ||||
-rw-r--r-- | activerecord/test/models/developer.rb | 17 |
4 files changed, 52 insertions, 0 deletions
diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG index 4ae82a6419..9ff29f1155 100644 --- a/activerecord/CHANGELOG +++ b/activerecord/CHANGELOG @@ -1,5 +1,16 @@ *Rails 3.1.0 (unreleased)* +* default_scope can take a block, lambda, or any other object which responds to `call` for lazy + evaluation: + + default_scope { ... } + default_scope lambda { ... } + default_scope method(:foo) + + This feature was originally implemented by Tim Morgan, but was then removed in favour of + defining a 'default_scope' class method, but has now been added back in by Jon Leighton. + The relevant lighthouse ticket is #1812. + * Default scopes are now evaluated at the latest possible moment, to avoid problems where scopes would be created which would implicitly contain the default scope, which would then be impossible to get rid of via Model.unscoped. diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 5b316c17be..9a01d793f9 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1196,6 +1196,15 @@ MSG # Article.new.published # => true # Article.create.published # => true # + # You can also use <tt>default_scope</tt> with a block, in order to have it lazily evaluated: + # + # class Article < ActiveRecord::Base + # default_scope { where(:published_at => Time.now - 1.week) } + # end + # + # (You can also pass any object which responds to <tt>call</tt> to the <tt>default_scope</tt> + # macro, and it will be called when building the default scope.) + # # If you need to do more complex things with a default scope, you can alternatively # define it as a class method: # @@ -1233,6 +1242,7 @@ end WARN end + scope = Proc.new if block_given? self.default_scopes = default_scopes.dup << scope end @@ -1245,6 +1255,8 @@ end default_scopes.inject(relation) do |default_scope, scope| if scope.is_a?(Hash) default_scope.apply_finder_options(scope) + elsif !scope.is_a?(Relation) && scope.respond_to?(:call) + default_scope.merge(scope.call) else default_scope.merge(scope) end diff --git a/activerecord/test/cases/relation_scoping_test.rb b/activerecord/test/cases/relation_scoping_test.rb index e231371cf8..2ed676fe69 100644 --- a/activerecord/test/cases/relation_scoping_test.rb +++ b/activerecord/test/cases/relation_scoping_test.rb @@ -312,6 +312,18 @@ class DefaultScopingTest < ActiveRecord::TestCase assert_equal [developers(:david).becomes(ClassMethodDeveloperCalledDavid)], ClassMethodDeveloperCalledDavid.all end + def test_default_scope_with_lambda + assert_equal [developers(:david).becomes(LazyLambdaDeveloperCalledDavid)], LazyLambdaDeveloperCalledDavid.all + end + + def test_default_scope_with_block + assert_equal [developers(:david).becomes(LazyBlockDeveloperCalledDavid)], LazyBlockDeveloperCalledDavid.all + end + + def test_default_scope_with_callable + assert_equal [developers(:david).becomes(CallableDeveloperCalledDavid)], CallableDeveloperCalledDavid.all + end + def test_default_scope_is_unscoped_on_find assert_equal 1, DeveloperCalledDavid.count assert_equal 11, DeveloperCalledDavid.unscoped.count diff --git a/activerecord/test/models/developer.rb b/activerecord/test/models/developer.rb index 93363f47c5..10701dd6fd 100644 --- a/activerecord/test/models/developer.rb +++ b/activerecord/test/models/developer.rb @@ -1,3 +1,5 @@ +require 'ostruct' + module DeveloperProjectsAssociationExtension def find_most_recent find(:first, :order => "id DESC") @@ -102,6 +104,21 @@ class DeveloperCalledDavid < ActiveRecord::Base default_scope where("name = 'David'") end +class LazyLambdaDeveloperCalledDavid < ActiveRecord::Base + self.table_name = 'developers' + default_scope lambda { where(:name => 'David') } +end + +class LazyBlockDeveloperCalledDavid < ActiveRecord::Base + self.table_name = 'developers' + default_scope { where(:name => 'David') } +end + +class CallableDeveloperCalledDavid < ActiveRecord::Base + self.table_name = 'developers' + default_scope OpenStruct.new(:call => where(:name => 'David')) +end + class ClassMethodDeveloperCalledDavid < ActiveRecord::Base self.table_name = 'developers' |