Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #8524: make_with_scope_protected.diff

File make_with_scope_protected.diff, 13.3 kB (added by josh, 2 years ago)
  • activerecord/test/abstract_unit.rb

    old new  
    7575  end 
    7676end 
    7777 
     78# Make with_scope public for tests 
     79class << ActiveRecord::Base 
     80  public :with_scope, :with_exclusive_scope 
     81end 
     82 
    7883#ActiveRecord::Base.logger = Logger.new(STDOUT) 
    7984#ActiveRecord::Base.colorize_logging = false 
  • activerecord/lib/active_record/associations/association_collection.rb

    old new  
    8585      end 
    8686       
    8787      def create(attrs = {}) 
    88         record = @reflection.klass.with_scope(:create => construct_scope[:create]) { @reflection.klass.create(attrs) }                 
     88        record = @reflection.klass.send(:with_scope, :create => construct_scope[:create]) { @reflection.klass.create(attrs) }                 
    8989        @target ||= [] unless loaded? 
    9090        @target << record  
    9191        record 
    9292      end 
    9393 
    9494      def create!(attrs = {}) 
    95         record = @reflection.klass.with_scope(:create => construct_scope[:create]) { @reflection.klass.create!(attrs) }                 
     95        record = @reflection.klass.send(:with_scope, :create => construct_scope[:create]) { @reflection.klass.create!(attrs) }                 
    9696        @target ||= [] unless loaded? 
    9797        @target << record  
    9898        record 
     
    161161          if @target.respond_to?(method) || (!@reflection.klass.respond_to?(method) && Class.respond_to?(method)) 
    162162            super 
    163163          else 
    164             @reflection.klass.with_scope(construct_scope) { @reflection.klass.send(method, *args, &block) } 
     164            @reflection.klass.send(:with_scope, construct_scope) { @reflection.klass.send(method, *args, &block) } 
    165165          end 
    166166        end 
    167167 
  • activerecord/lib/active_record/associations/has_one_association.rb

    old new  
    8080          # instance. Otherwise, if the target has not previously been loaded 
    8181          # elsewhere, the instance we create will get orphaned. 
    8282          load_target if replace_existing 
    83           record = @reflection.klass.with_scope(:create => construct_scope[:create]) { yield @reflection.klass } 
     83          record = @reflection.klass.send(:with_scope, :create => construct_scope[:create]) { yield @reflection.klass } 
    8484 
    8585          if replace_existing 
    8686            replace(record, true)  
  • activerecord/lib/active_record/associations/has_many_through_association.rb

    old new  
    5757            raise_on_type_mismatch(associate) 
    5858            raise ActiveRecord::HasManyThroughCantAssociateNewRecords.new(@owner, through) unless associate.respond_to?(:new_record?) && !associate.new_record? 
    5959 
    60             @owner.send(@reflection.through_reflection.name).proxy_target << klass.with_scope(:create => construct_join_attributes(associate)) { klass.create! } 
     60            @owner.send(@reflection.through_reflection.name).proxy_target << klass.send(:with_scope, :create => construct_join_attributes(associate)) { klass.create! } 
    6161            @target << associate if loaded? 
    6262          end 
    6363        end 
     
    9191 
    9292      def create!(attrs = nil) 
    9393        @reflection.klass.transaction do 
    94           self << @reflection.klass.with_scope(:create => attrs) { @reflection.klass.create! } 
     94          self << @reflection.klass.send(:with_scope, :create => attrs) { @reflection.klass.create! } 
    9595        end 
    9696      end 
    9797 
     
    105105          if @target.respond_to?(method) || (!@reflection.klass.respond_to?(method) && Class.respond_to?(method)) 
    106106            super 
    107107          else 
    108             @reflection.klass.with_scope(construct_scope) { @reflection.klass.send(method, *args, &block) } 
     108            @reflection.klass.send(:with_scope, construct_scope) { @reflection.klass.send(method, *args, &block) } 
    109109          end 
    110110        end 
    111111 
  • activerecord/lib/active_record/base.rb

    old new  
    947947        logger.level = old_logger_level if logger 
    948948      end 
    949949 
    950       # Scope parameters to method calls within the block.  Takes a hash of method_name => parameters hash. 
    951       # method_name may be :find or :create. :find parameters may include the <tt>:conditions</tt>, <tt>:joins</tt>, 
    952       # <tt>:include</tt>, <tt>:offset</tt>, <tt>:limit</tt>, and <tt>:readonly</tt> options. :create parameters are an attributes hash. 
    953       # 
    954       #   Article.with_scope(:find => { :conditions => "blog_id = 1" }, :create => { :blog_id => 1 }) do 
    955       #     Article.find(1) # => SELECT * from articles WHERE blog_id = 1 AND id = 1 
    956       #     a = Article.create(1) 
    957       #     a.blog_id # => 1 
    958       #   end 
    959       # 
    960       # In nested scopings, all previous parameters are overwritten by inner rule 
    961       # except :conditions in :find, that are merged as hash. 
    962       # 
    963       #   Article.with_scope(:find => { :conditions => "blog_id = 1", :limit => 1 }, :create => { :blog_id => 1 }) do 
    964       #     Article.with_scope(:find => { :limit => 10}) 
    965       #       Article.find(:all) # => SELECT * from articles WHERE blog_id = 1 LIMIT 10 
    966       #     end 
    967       #     Article.with_scope(:find => { :conditions => "author_id = 3" }) 
    968       #       Article.find(:all) # => SELECT * from articles WHERE blog_id = 1 AND author_id = 3 LIMIT 1 
    969       #     end 
    970       #   end 
    971       # 
    972       # You can ignore any previous scopings by using <tt>with_exclusive_scope</tt> method. 
    973       # 
    974       #   Article.with_scope(:find => { :conditions => "blog_id = 1", :limit => 1 }) do 
    975       #     Article.with_exclusive_scope(:find => { :limit => 10 }) 
    976       #       Article.find(:all) # => SELECT * from articles LIMIT 10 
    977       #     end 
    978       #   end 
    979       def with_scope(method_scoping = {}, action = :merge, &block) 
    980         method_scoping = method_scoping.method_scoping if method_scoping.respond_to?(:method_scoping) 
    981  
    982         # Dup first and second level of hash (method and params). 
    983         method_scoping = method_scoping.inject({}) do |hash, (method, params)| 
    984           hash[method] = (params == true) ? params : params.dup 
    985           hash 
    986         end 
    987  
    988         method_scoping.assert_valid_keys([ :find, :create ]) 
    989  
    990         if f = method_scoping[:find] 
    991           f.assert_valid_keys([ :conditions, :joins, :select, :include, :from, :offset, :limit, :order, :readonly, :lock ]) 
    992           set_readonly_option! f 
    993         end 
    994  
    995         # Merge scopings 
    996         if action == :merge && current_scoped_methods 
    997           method_scoping = current_scoped_methods.inject(method_scoping) do |hash, (method, params)| 
    998             case hash[method] 
    999               when Hash 
    1000                 if method == :find 
    1001                   (hash[method].keys + params.keys).uniq.each do |key| 
    1002                     merge = hash[method][key] && params[key] # merge if both scopes have the same key 
    1003                     if key == :conditions && merge 
    1004                       hash[method][key] = [params[key], hash[method][key]].collect{ |sql| "( %s )" % sanitize_sql(sql) }.join(" AND ") 
    1005                     elsif key == :include && merge 
    1006                       hash[method][key] = merge_includes(hash[method][key], params[key]).uniq 
    1007                     else 
    1008                       hash[method][key] = hash[method][key] || params[key] 
    1009                     end 
    1010                   end 
    1011                 else 
    1012                   hash[method] = params.merge(hash[method]) 
    1013                 end 
    1014               else 
    1015                 hash[method] = params 
    1016             end 
    1017             hash 
    1018           end 
    1019         end 
    1020  
    1021         self.scoped_methods << method_scoping 
    1022  
    1023         begin 
    1024           yield 
    1025         ensure 
    1026           self.scoped_methods.pop 
    1027         end 
    1028       end 
    1029  
    1030       # Works like with_scope, but discards any nested properties. 
    1031       def with_exclusive_scope(method_scoping = {}, &block) 
    1032         with_scope(method_scoping, :overwrite, &block) 
    1033       end 
    1034  
    1035950      # Overwrite the default class equality method to provide support for association proxies. 
    1036951      def ===(object) 
    1037952        object.is_a?(self) 
     
    14091324        end 
    14101325 
    14111326      protected 
     1327        # Scope parameters to method calls within the block.  Takes a hash of method_name => parameters hash. 
     1328        # method_name may be :find or :create. :find parameters may include the <tt>:conditions</tt>, <tt>:joins</tt>, 
     1329        # <tt>:include</tt>, <tt>:offset</tt>, <tt>:limit</tt>, and <tt>:readonly</tt> options. :create parameters are an attributes hash. 
     1330        # 
     1331        #   class Article < ActiveRecord::Base 
     1332        #     def self.create_with_scope 
     1333        #       with_scope(:find => { :conditions => "blog_id = 1" }, :create => { :blog_id => 1 }) do 
     1334        #         find(1) # => SELECT * from articles WHERE blog_id = 1 AND id = 1 
     1335        #         a = create(1) 
     1336        #         a.blog_id # => 1 
     1337        #       end 
     1338        #     end 
     1339        #   end 
     1340        # 
     1341        # In nested scopings, all previous parameters are overwritten by inner rule 
     1342        # except :conditions in :find, that are merged as hash. 
     1343        # 
     1344        #   class Article < ActiveRecord::Base 
     1345        #     def self.find_with_scope 
     1346        #       with_scope(:find => { :conditions => "blog_id = 1", :limit => 1 }, :create => { :blog_id => 1 }) do 
     1347        #         with_scope(:find => { :limit => 10}) 
     1348        #           find(:all) # => SELECT * from articles WHERE blog_id = 1 LIMIT 10 
     1349        #         end 
     1350        #         with_scope(:find => { :conditions => "author_id = 3" }) 
     1351        #           find(:all) # => SELECT * from articles WHERE blog_id = 1 AND author_id = 3 LIMIT 1 
     1352        #         end 
     1353        #       end 
     1354        #     end 
     1355        #   end 
     1356        # 
     1357        # You can ignore any previous scopings by using <tt>with_exclusive_scope</tt> method. 
     1358        # 
     1359        #   class Article < ActiveRecord::Base 
     1360        #     def self.find_with_exclusive_scope 
     1361        #       with_scope(:find => { :conditions => "blog_id = 1", :limit => 1 }) do 
     1362        #         with_exclusive_scope(:find => { :limit => 10 }) 
     1363        #           find(:all) # => SELECT * from articles LIMIT 10 
     1364        #         end 
     1365        #       end 
     1366        #     end 
     1367        #   end 
     1368        def with_scope(method_scoping = {}, action = :merge, &block) 
     1369          method_scoping = method_scoping.method_scoping if method_scoping.respond_to?(:method_scoping) 
     1370 
     1371          # Dup first and second level of hash (method and params). 
     1372          method_scoping = method_scoping.inject({}) do |hash, (method, params)| 
     1373            hash[method] = (params == true) ? params : params.dup 
     1374            hash 
     1375          end 
     1376 
     1377          method_scoping.assert_valid_keys([ :find, :create ]) 
     1378 
     1379          if f = method_scoping[:find] 
     1380            f.assert_valid_keys([ :conditions, :joins, :select, :include, :from, :offset, :limit, :order, :readonly, :lock ]) 
     1381            set_readonly_option! f 
     1382          end 
     1383 
     1384          # Merge scopings 
     1385          if action == :merge && current_scoped_methods 
     1386            method_scoping = current_scoped_methods.inject(method_scoping) do |hash, (method, params)| 
     1387              case hash[method] 
     1388                when Hash 
     1389                  if method == :find 
     1390                    (hash[method].keys + params.keys).uniq.each do |key| 
     1391                      merge = hash[method][key] && params[key] # merge if both scopes have the same key 
     1392                      if key == :conditions && merge 
     1393                        hash[method][key] = [params[key], hash[method][key]].collect{ |sql| "( %s )" % sanitize_sql(sql) }.join(" AND ") 
     1394                      elsif key == :include && merge 
     1395                        hash[method][key] = merge_includes(hash[method][key], params[key]).uniq 
     1396                      else 
     1397                        hash[method][key] = hash[method][key] || params[key] 
     1398                      end 
     1399                    end 
     1400                  else 
     1401                    hash[method] = params.merge(hash[method]) 
     1402                  end 
     1403                else 
     1404                  hash[method] = params 
     1405              end 
     1406              hash 
     1407            end 
     1408          end 
     1409 
     1410          self.scoped_methods << method_scoping 
     1411 
     1412          begin 
     1413            yield 
     1414          ensure 
     1415            self.scoped_methods.pop 
     1416          end 
     1417        end 
     1418 
     1419        # Works like with_scope, but discards any nested properties. 
     1420        def with_exclusive_scope(method_scoping = {}, &block) 
     1421          with_scope(method_scoping, :overwrite, &block) 
     1422        end 
     1423 
    14121424        def subclasses #:nodoc: 
    14131425          @@subclasses[self] ||= [] 
    14141426          @@subclasses[self] + extra = @@subclasses[self].inject([]) {|list, subclass| list + subclass.subclasses }