Skip to content
This repository
Browse code

extract #with_scope and #with_exclusive_scope to active_record_deprec…

…ated_finders
  • Loading branch information...
commit d242e467819a428ad7e302968e4c9fa1e26d9326 1 parent af27c8b
Jon Leighton jonleighton authored
5 activerecord/lib/active_record/relation.rb
@@ -236,7 +236,10 @@ def many?
236 236 # Please check unscoped if you want to remove all previous scopes (including
237 237 # the default_scope) during the execution of a block.
238 238 def scoping
239   - @klass.with_scope(self, :overwrite) { yield }
  239 + previous, klass.current_scope = klass.current_scope, self
  240 + yield
  241 + ensure
  242 + klass.current_scope = previous
240 243 end
241 244
242 245 # Updates all records with details given if they match a set of conditions supplied, limits and order can
121 activerecord/lib/active_record/scoping.rb
@@ -10,118 +10,6 @@ module Scoping
10 10 end
11 11
12 12 module ClassMethods
13   - # with_scope lets you apply options to inner block incrementally. It takes a hash and the keys must be
14   - # <tt>:find</tt> or <tt>:create</tt>. <tt>:find</tt> parameter is <tt>Relation</tt> while
15   - # <tt>:create</tt> parameters are an attributes hash.
16   - #
17   - # class Article < ActiveRecord::Base
18   - # def self.create_with_scope
19   - # with_scope(:find => where(:blog_id => 1), :create => { :blog_id => 1 }) do
20   - # find(1) # => SELECT * from articles WHERE blog_id = 1 AND id = 1
21   - # a = create(1)
22   - # a.blog_id # => 1
23   - # end
24   - # end
25   - # end
26   - #
27   - # In nested scopings, all previous parameters are overwritten by the innermost rule, with the exception of
28   - # <tt>where</tt>, <tt>includes</tt>, and <tt>joins</tt> operations in <tt>Relation</tt>, which are merged.
29   - #
30   - # <tt>joins</tt> operations are uniqued so multiple scopes can join in the same table without table aliasing
31   - # problems. If you need to join multiple tables, but still want one of the tables to be uniqued, use the
32   - # array of strings format for your joins.
33   - #
34   - # class Article < ActiveRecord::Base
35   - # def self.find_with_scope
36   - # with_scope(:find => where(:blog_id => 1).limit(1), :create => { :blog_id => 1 }) do
37   - # with_scope(:find => limit(10)) do
38   - # all # => SELECT * from articles WHERE blog_id = 1 LIMIT 10
39   - # end
40   - # with_scope(:find => where(:author_id => 3)) do
41   - # all # => SELECT * from articles WHERE blog_id = 1 AND author_id = 3 LIMIT 1
42   - # end
43   - # end
44   - # end
45   - # end
46   - #
47   - # You can ignore any previous scopings by using the <tt>with_exclusive_scope</tt> method.
48   - #
49   - # class Article < ActiveRecord::Base
50   - # def self.find_with_exclusive_scope
51   - # with_scope(:find => where(:blog_id => 1).limit(1)) do
52   - # with_exclusive_scope(:find => limit(10)) do
53   - # all # => SELECT * from articles LIMIT 10
54   - # end
55   - # end
56   - # end
57   - # end
58   - #
59   - # *Note*: the +:find+ scope also has effect on update and deletion methods, like +update_all+ and +delete_all+.
60   - def with_scope(scope = {}, action = :merge, &block)
61   - # If another Active Record class has been passed in, get its current scope
62   - scope = scope.current_scope if !scope.is_a?(Relation) && scope.respond_to?(:current_scope)
63   -
64   - previous_scope = self.current_scope
65   -
66   - if scope.is_a?(Hash)
67   - # Dup first and second level of hash (method and params).
68   - scope = scope.dup
69   - scope.each do |method, params|
70   - scope[method] = params.dup unless params == true
71   - end
72   -
73   - scope.assert_valid_keys([ :find, :create ])
74   - relation = construct_finder_arel(scope[:find] || {})
75   - relation.default_scoped = true unless action == :overwrite
76   -
77   - if previous_scope && previous_scope.create_with_value && scope[:create]
78   - scope_for_create = if action == :merge
79   - previous_scope.create_with_value.merge(scope[:create])
80   - else
81   - scope[:create]
82   - end
83   -
84   - relation = relation.create_with(scope_for_create)
85   - else
86   - scope_for_create = scope[:create]
87   - scope_for_create ||= previous_scope.create_with_value if previous_scope
88   - relation = relation.create_with(scope_for_create) if scope_for_create
89   - end
90   -
91   - scope = relation
92   - end
93   -
94   - scope = previous_scope.merge(scope) if previous_scope && action == :merge
95   -
96   - self.current_scope = scope
97   - begin
98   - yield
99   - ensure
100   - self.current_scope = previous_scope
101   - end
102   - end
103   -
104   - protected
105   -
106   - # Works like with_scope, but discards any nested properties.
107   - def with_exclusive_scope(method_scoping = {}, &block)
108   - if method_scoping.values.any? { |e| e.is_a?(ActiveRecord::Relation) }
109   - raise ArgumentError, <<-MSG
110   - New finder API can not be used with_exclusive_scope. You can either call unscoped to get an anonymous scope not bound to the default_scope:
111   -
112   - User.unscoped.where(:active => true)
113   -
114   - Or call unscoped with a block:
115   -
116   - User.unscoped do
117   - User.where(:active => true).all
118   - end
119   -
120   - MSG
121   - end
122   - with_scope(method_scoping, :overwrite, &block)
123   - end
124   -
125 13 def current_scope #:nodoc:
126 14 Thread.current["#{self}_current_scope"]
127 15 end
@@ -129,15 +17,6 @@ def current_scope #:nodoc:
129 17 def current_scope=(scope) #:nodoc:
130 18 Thread.current["#{self}_current_scope"] = scope
131 19 end
132   -
133   - private
134   -
135   - def construct_finder_arel(options = {}, scope = nil)
136   - relation = options.is_a?(Hash) ? unscoped.apply_finder_options(options) : options
137   - relation = scope.merge(relation) if scope
138   - relation
139   - end
140   -
141 20 end
142 21
143 22 def populate_with_current_scope_attributes

0 comments on commit d242e46

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