From 256b363eeecf6d0fb896aabd3fc619e200a5062c Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Sun, 17 Apr 2011 20:47:52 +0100 Subject: Revert "Deprecate defining scopes with a callable (lambda, proc, etc) via the scope class method. Just define a class method yourself instead." This reverts commit f0e198bfa1e3f9689e0cde1d194a44027fc90b3c. Conflicts: activerecord/test/models/post.rb --- activerecord/CHANGELOG | 18 -------- activerecord/lib/active_record/named_scope.rb | 62 +-------------------------- activerecord/test/cases/named_scope_test.rb | 6 --- activerecord/test/models/comment.rb | 5 +-- activerecord/test/models/post.rb | 20 ++++----- activerecord/test/models/topic.rb | 26 +++++------ 6 files changed, 23 insertions(+), 114 deletions(-) diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG index 93eb42a52c..6b3d408720 100644 --- a/activerecord/CHANGELOG +++ b/activerecord/CHANGELOG @@ -1,23 +1,5 @@ *Rails 3.1.0 (unreleased)* -* Passing a proc (or other object that responds to #call) to scope is deprecated. If you need your - scope to be lazily evaluated, or takes parameters, please define it as a normal class method - instead. For example, change this: - - class Post < ActiveRecord::Base - scope :unpublished, lambda { where('published_at > ?', Time.now) } - end - - To this: - - class Post < ActiveRecord::Base - def self.unpublished - where('published_at > ?', Time.now) - end - end - - [Jon Leighton] - * 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/named_scope.rb b/activerecord/lib/active_record/named_scope.rb index f1df04950b..60840e6958 100644 --- a/activerecord/lib/active_record/named_scope.rb +++ b/activerecord/lib/active_record/named_scope.rb @@ -51,14 +51,6 @@ module ActiveRecord # The above calls to scope define class methods Shirt.red and Shirt.dry_clean_only. Shirt.red, # in effect, represents the query Shirt.where(:color => 'red'). # - # Note that this is simply 'syntactic sugar' for defining an actual class method: - # - # class Shirt < ActiveRecord::Base - # def self.red - # where(:color => 'red') - # end - # end - # # Unlike Shirt.find(...), however, the object returned by Shirt.red is not an Array; it # resembles the association object constructed by a has_many declaration. For instance, # you can invoke Shirt.red.first, Shirt.red.count, Shirt.red.where(:size => 'small'). @@ -82,34 +74,14 @@ module ActiveRecord # then elton.shirts.red.dry_clean_only will return all of Elton's red, dry clean # only shirts. # - # If you need to pass parameters to a scope, define it as a normal method: + # Named \scopes can also be procedural: # # class Shirt < ActiveRecord::Base - # def self.colored(color) - # where(:color => color) - # end + # scope :colored, lambda {|color| where(:color => color) } # end # # In this example, Shirt.colored('puce') finds all puce shirts. # - # Note that scopes defined with \scope will be evaluated when they are defined, rather than - # when they are used. For example, the following would be incorrect: - # - # class Post < ActiveRecord::Base - # scope :recent, where('published_at >= ?', Time.now - 1.week) - # end - # - # The example above would be 'frozen' to the Time.now value when the Post - # class was defined, and so the resultant SQL query would always be the same. The correct - # way to do this would be via a class method, which will re-evaluate the scope each time - # it is called: - # - # class Post < ActiveRecord::Base - # def self.recent - # where('published_at >= ?', Time.now - 1.week) - # end - # end - # # Named \scopes can also have extensions, just as with has_many declarations: # # class Shirt < ActiveRecord::Base @@ -120,18 +92,6 @@ module ActiveRecord # end # end # - # The above could also be written as a class method like so: - # - # class Shirt < ActiveRecord::Base - # def self.red - # where(:color => 'red').extending do - # def dom_id - # 'red_shirts' - # end - # end - # end - # end - # # Scopes can also be used while creating/building a record. # # class Article < ActiveRecord::Base @@ -168,24 +128,6 @@ module ActiveRecord valid_scope_name?(name) extension = Module.new(&Proc.new) if block_given? - if !scope_options.is_a?(Relation) && scope_options.respond_to?(:call) - ActiveSupport::Deprecation.warn <<-WARN -Passing a proc (or other object that responds to #call) to scope is deprecated. If you need your scope to be lazily evaluated, or takes parameters, please define it as a normal class method instead. For example, change this: - -class Post < ActiveRecord::Base - scope :unpublished, lambda { where('published_at > ?', Time.now) } -end - -To this: - -class Post < ActiveRecord::Base - def self.unpublished - where('published_at > ?', Time.now) - end -end - WARN - end - scope_proc = lambda do |*args| options = scope_options.respond_to?(:call) ? scope_options.call(*args) : scope_options options = scoped.apply_finder_options(options) if options.is_a?(Hash) diff --git a/activerecord/test/cases/named_scope_test.rb b/activerecord/test/cases/named_scope_test.rb index 2880fdc651..8fd1fc2577 100644 --- a/activerecord/test/cases/named_scope_test.rb +++ b/activerecord/test/cases/named_scope_test.rb @@ -471,12 +471,6 @@ class NamedScopeTest < ActiveRecord::TestCase require "models/without_table" end end - - def test_scopes_with_callables_are_deprecated - assert_deprecated do - Post.scope :WE_SO_EXCITED, lambda { |partyingpartyingpartying, yeah| fun!.fun!.fun! } - end - end end class DynamicScopeMatchTest < ActiveRecord::TestCase diff --git a/activerecord/test/models/comment.rb b/activerecord/test/models/comment.rb index 3bd7db7834..2a4c37089a 100644 --- a/activerecord/test/models/comment.rb +++ b/activerecord/test/models/comment.rb @@ -1,8 +1,5 @@ class Comment < ActiveRecord::Base - def self.limit_by(l) - limit(l) - end - + scope :limit_by, lambda {|l| limit(l) } scope :containing_the_letter_e, :conditions => "comments.body LIKE '%e%'" scope :not_again, where("comments.body NOT LIKE '%again%'") scope :for_first_post, :conditions => { :post_id => 1 } diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb index a91c10276b..34cea60053 100644 --- a/activerecord/test/models/post.rb +++ b/activerecord/test/models/post.rb @@ -8,13 +8,12 @@ class Post < ActiveRecord::Base scope :containing_the_letter_a, where("body LIKE '%a%'") scope :ranked_by_comments, order("comments_count DESC") - def self.limit_by(l) - limit(l) - end - - def self.with_authors_at_address(address) - where('authors.author_address_id = ?', address.id).joins('JOIN authors ON authors.id = posts.author_id') - end + scope :limit_by, lambda {|l| limit(l) } + scope :with_authors_at_address, lambda { |address| { + :conditions => [ 'authors.author_address_id = ?', address.id ], + :joins => 'JOIN authors ON authors.id = posts.author_id' + } + } belongs_to :author do def greeting @@ -29,10 +28,9 @@ class Post < ActiveRecord::Base scope :with_special_comments, :joins => :comments, :conditions => {:comments => {:type => 'SpecialComment'} } scope :with_very_special_comments, joins(:comments).where(:comments => {:type => 'VerySpecialComment'}) - - def self.with_post(post_id) - joins(:comments).where(:comments => { :post_id => post_id }) - end + scope :with_post, lambda {|post_id| + { :joins => :comments, :conditions => {:comments => {:post_id => post_id} } } + } has_many :comments do def find_most_recent diff --git a/activerecord/test/models/topic.rb b/activerecord/test/models/topic.rb index 60e750e6c4..6440dbe8ab 100644 --- a/activerecord/test/models/topic.rb +++ b/activerecord/test/models/topic.rb @@ -1,20 +1,10 @@ class Topic < ActiveRecord::Base scope :base - - ActiveSupport::Deprecation.silence do - scope :written_before, lambda { |time| - if time - { :conditions => ['written_on < ?', time] } - end - } - - scope :with_object, Class.new(Struct.new(:klass)) { - def call - klass.where(:approved => true) - end - }.new(self) - end - + scope :written_before, lambda { |time| + if time + { :conditions => ['written_on < ?', time] } + end + } scope :approved, :conditions => {:approved => true} scope :rejected, :conditions => {:approved => false} @@ -29,6 +19,12 @@ class Topic < ActiveRecord::Base end end + scope :with_object, Class.new(Struct.new(:klass)) { + def call + klass.where(:approved => true) + end + }.new(self) + module NamedExtension def two 2 -- cgit v1.2.3