Skip to content
This repository
Browse code

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 f0e198b.

Conflicts:

	activerecord/test/models/post.rb
  • Loading branch information...
commit 256b363eeecf6d0fb896aabd3fc619e200a5062c 1 parent d1f10e7
Jon Leighton jonleighton authored
18 activerecord/CHANGELOG
... ... @@ -1,23 +1,5 @@
1 1 *Rails 3.1.0 (unreleased)*
2 2
3   -* Passing a proc (or other object that responds to #call) to scope is deprecated. If you need your
4   - scope to be lazily evaluated, or takes parameters, please define it as a normal class method
5   - instead. For example, change this:
6   -
7   - class Post < ActiveRecord::Base
8   - scope :unpublished, lambda { where('published_at > ?', Time.now) }
9   - end
10   -
11   - To this:
12   -
13   - class Post < ActiveRecord::Base
14   - def self.unpublished
15   - where('published_at > ?', Time.now)
16   - end
17   - end
18   -
19   - [Jon Leighton]
20   -
21 3 * Default scopes are now evaluated at the latest possible moment, to avoid problems where
22 4 scopes would be created which would implicitly contain the default scope, which would then
23 5 be impossible to get rid of via Model.unscoped.
62 activerecord/lib/active_record/named_scope.rb
@@ -51,14 +51,6 @@ def scoped(options = nil)
51 51 # The above calls to <tt>scope</tt> define class methods Shirt.red and Shirt.dry_clean_only. Shirt.red,
52 52 # in effect, represents the query <tt>Shirt.where(:color => 'red')</tt>.
53 53 #
54   - # Note that this is simply 'syntactic sugar' for defining an actual class method:
55   - #
56   - # class Shirt < ActiveRecord::Base
57   - # def self.red
58   - # where(:color => 'red')
59   - # end
60   - # end
61   - #
62 54 # Unlike <tt>Shirt.find(...)</tt>, however, the object returned by Shirt.red is not an Array; it
63 55 # resembles the association object constructed by a <tt>has_many</tt> declaration. For instance,
64 56 # you can invoke <tt>Shirt.red.first</tt>, <tt>Shirt.red.count</tt>, <tt>Shirt.red.where(:size => 'small')</tt>.
@@ -82,34 +74,14 @@ def scoped(options = nil)
82 74 # then <tt>elton.shirts.red.dry_clean_only</tt> will return all of Elton's red, dry clean
83 75 # only shirts.
84 76 #
85   - # If you need to pass parameters to a scope, define it as a normal method:
  77 + # Named \scopes can also be procedural:
86 78 #
87 79 # class Shirt < ActiveRecord::Base
88   - # def self.colored(color)
89   - # where(:color => color)
90   - # end
  80 + # scope :colored, lambda {|color| where(:color => color) }
91 81 # end
92 82 #
93 83 # In this example, <tt>Shirt.colored('puce')</tt> finds all puce shirts.
94 84 #
95   - # Note that scopes defined with \scope will be evaluated when they are defined, rather than
96   - # when they are used. For example, the following would be incorrect:
97   - #
98   - # class Post < ActiveRecord::Base
99   - # scope :recent, where('published_at >= ?', Time.now - 1.week)
100   - # end
101   - #
102   - # The example above would be 'frozen' to the <tt>Time.now</tt> value when the <tt>Post</tt>
103   - # class was defined, and so the resultant SQL query would always be the same. The correct
104   - # way to do this would be via a class method, which will re-evaluate the scope each time
105   - # it is called:
106   - #
107   - # class Post < ActiveRecord::Base
108   - # def self.recent
109   - # where('published_at >= ?', Time.now - 1.week)
110   - # end
111   - # end
112   - #
113 85 # Named \scopes can also have extensions, just as with <tt>has_many</tt> declarations:
114 86 #
115 87 # class Shirt < ActiveRecord::Base
@@ -120,18 +92,6 @@ def scoped(options = nil)
120 92 # end
121 93 # end
122 94 #
123   - # The above could also be written as a class method like so:
124   - #
125   - # class Shirt < ActiveRecord::Base
126   - # def self.red
127   - # where(:color => 'red').extending do
128   - # def dom_id
129   - # 'red_shirts'
130   - # end
131   - # end
132   - # end
133   - # end
134   - #
135 95 # Scopes can also be used while creating/building a record.
136 96 #
137 97 # class Article < ActiveRecord::Base
@@ -168,24 +128,6 @@ def scope(name, scope_options = {})
168 128 valid_scope_name?(name)
169 129 extension = Module.new(&Proc.new) if block_given?
170 130
171   - if !scope_options.is_a?(Relation) && scope_options.respond_to?(:call)
172   - ActiveSupport::Deprecation.warn <<-WARN
173   -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:
174   -
175   -class Post < ActiveRecord::Base
176   - scope :unpublished, lambda { where('published_at > ?', Time.now) }
177   -end
178   -
179   -To this:
180   -
181   -class Post < ActiveRecord::Base
182   - def self.unpublished
183   - where('published_at > ?', Time.now)
184   - end
185   -end
186   - WARN
187   - end
188   -
189 131 scope_proc = lambda do |*args|
190 132 options = scope_options.respond_to?(:call) ? scope_options.call(*args) : scope_options
191 133 options = scoped.apply_finder_options(options) if options.is_a?(Hash)
6 activerecord/test/cases/named_scope_test.rb
@@ -471,12 +471,6 @@ def test_scoped_are_lazy_loaded_if_table_still_does_not_exist
471 471 require "models/without_table"
472 472 end
473 473 end
474   -
475   - def test_scopes_with_callables_are_deprecated
476   - assert_deprecated do
477   - Post.scope :WE_SO_EXCITED, lambda { |partyingpartyingpartying, yeah| fun!.fun!.fun! }
478   - end
479   - end
480 474 end
481 475
482 476 class DynamicScopeMatchTest < ActiveRecord::TestCase
5 activerecord/test/models/comment.rb
... ... @@ -1,8 +1,5 @@
1 1 class Comment < ActiveRecord::Base
2   - def self.limit_by(l)
3   - limit(l)
4   - end
5   -
  2 + scope :limit_by, lambda {|l| limit(l) }
6 3 scope :containing_the_letter_e, :conditions => "comments.body LIKE '%e%'"
7 4 scope :not_again, where("comments.body NOT LIKE '%again%'")
8 5 scope :for_first_post, :conditions => { :post_id => 1 }
20 activerecord/test/models/post.rb
@@ -8,13 +8,12 @@ def author
8 8 scope :containing_the_letter_a, where("body LIKE '%a%'")
9 9 scope :ranked_by_comments, order("comments_count DESC")
10 10
11   - def self.limit_by(l)
12   - limit(l)
13   - end
14   -
15   - def self.with_authors_at_address(address)
16   - where('authors.author_address_id = ?', address.id).joins('JOIN authors ON authors.id = posts.author_id')
17   - end
  11 + scope :limit_by, lambda {|l| limit(l) }
  12 + scope :with_authors_at_address, lambda { |address| {
  13 + :conditions => [ 'authors.author_address_id = ?', address.id ],
  14 + :joins => 'JOIN authors ON authors.id = posts.author_id'
  15 + }
  16 + }
18 17
19 18 belongs_to :author do
20 19 def greeting
@@ -29,10 +28,9 @@ def greeting
29 28
30 29 scope :with_special_comments, :joins => :comments, :conditions => {:comments => {:type => 'SpecialComment'} }
31 30 scope :with_very_special_comments, joins(:comments).where(:comments => {:type => 'VerySpecialComment'})
32   -
33   - def self.with_post(post_id)
34   - joins(:comments).where(:comments => { :post_id => post_id })
35   - end
  31 + scope :with_post, lambda {|post_id|
  32 + { :joins => :comments, :conditions => {:comments => {:post_id => post_id} } }
  33 + }
36 34
37 35 has_many :comments do
38 36 def find_most_recent
26 activerecord/test/models/topic.rb
... ... @@ -1,20 +1,10 @@
1 1 class Topic < ActiveRecord::Base
2 2 scope :base
3   -
4   - ActiveSupport::Deprecation.silence do
5   - scope :written_before, lambda { |time|
6   - if time
7   - { :conditions => ['written_on < ?', time] }
8   - end
9   - }
10   -
11   - scope :with_object, Class.new(Struct.new(:klass)) {
12   - def call
13   - klass.where(:approved => true)
14   - end
15   - }.new(self)
16   - end
17   -
  3 + scope :written_before, lambda { |time|
  4 + if time
  5 + { :conditions => ['written_on < ?', time] }
  6 + end
  7 + }
18 8 scope :approved, :conditions => {:approved => true}
19 9 scope :rejected, :conditions => {:approved => false}
20 10
@@ -29,6 +19,12 @@ def one
29 19 end
30 20 end
31 21
  22 + scope :with_object, Class.new(Struct.new(:klass)) {
  23 + def call
  24 + klass.where(:approved => true)
  25 + end
  26 + }.new(self)
  27 +
32 28 module NamedExtension
33 29 def two
34 30 2

0 comments on commit 256b363

Please sign in to comment.
Something went wrong with that request. Please try again.