From 85a743e805117fed447656d45de067865e13baa1 Mon Sep 17 00:00:00 2001 From: Ken Collins Date: Tue, 5 May 2009 17:06:13 -0400 Subject: [PATCH] Remove 1.2.6 and 2.0.1 support which used named scope hacks. --- README.rdoc | 2 +- Rakefile | 4 +- grouped_scope.gemspec | 6 - lib/grouped_scope/has_many_association.rb | 2 - .../association_reflection_test.rb | 12 +- test/lib/boot.rb | 1 - test/lib/core_ext.rb | 20 --- test/lib/named_scope.rb | 7 - test/lib/named_scope/core_ext.rb | 82 --------- test/lib/named_scope/named_scope.rb | 168 ------------------ test/lib/named_scope/named_scope_patch_1.2.rb | 85 --------- test/lib/named_scope/named_scope_patch_2.0.rb | 55 ------ 12 files changed, 5 insertions(+), 439 deletions(-) delete mode 100644 test/lib/core_ext.rb delete mode 100755 test/lib/named_scope.rb delete mode 100755 test/lib/named_scope/core_ext.rb delete mode 100755 test/lib/named_scope/named_scope.rb delete mode 100755 test/lib/named_scope/named_scope_patch_1.2.rb delete mode 100755 test/lib/named_scope/named_scope_patch_2.0.rb diff --git a/README.rdoc b/README.rdoc index 6697038..fb29c3f 100644 --- a/README.rdoc +++ b/README.rdoc @@ -5,7 +5,7 @@ GroupedScope aims to make two things easier in your ActiveRecord models. First, easy way to group objects, second, to allow the group to share associated object via existing has_many relationships. See installation and usage for more details. -By the way, this plugin has been tested with rails 1.2.6, 2.0.4, and 2.1.1. +By the way, this plugin has been tested with rails 2.3.2, 2.2.2, and 2.1.1 === Installation & Usage diff --git a/Rakefile b/Rakefile index 316c5ad..7261442 100644 --- a/Rakefile +++ b/Rakefile @@ -20,10 +20,10 @@ Rake::TestTask.new(:test) do |t| t.verbose = true end -desc 'Test the GroupedScope plugin with Rails 2.1.1, 2.0.4 & 1.2.6 gems' +desc 'Test the GroupedScope plugin with Rails 2.3.2, 2.2.2, and 2.1.1 gems' task :test_rails do test = Rake::Task['test'] - versions = ['2.2.2','2.1.1','2.0.4','1.2.6'] + versions = ['2.3.2','2.2.2','2.1.1'] versions.each do |version| ENV['RAILS_VERSION'] = "#{version}" test.invoke diff --git a/grouped_scope.gemspec b/grouped_scope.gemspec index 50234ef..51360d6 100644 --- a/grouped_scope.gemspec +++ b/grouped_scope.gemspec @@ -33,12 +33,6 @@ Gem::Specification.new do |s| "test/grouped_scope/self_grouping_test.rb", "test/helper.rb", "test/lib/boot.rb", - "test/lib/core_ext.rb", - "test/lib/named_scope.rb", - "test/lib/named_scope/core_ext.rb", - "test/lib/named_scope/named_scope.rb", - "test/lib/named_scope/named_scope_patch_1.2.rb", - "test/lib/named_scope/named_scope_patch_2.0.rb", "test/lib/test_case.rb" ] s.rdoc_options = ["--main", "README.rdoc"] s.extra_rdoc_files = ["README.rdoc","CHANGELOG","MIT-LICENSE"] diff --git a/lib/grouped_scope/has_many_association.rb b/lib/grouped_scope/has_many_association.rb index af83c2d..6f02b72 100644 --- a/lib/grouped_scope/has_many_association.rb +++ b/lib/grouped_scope/has_many_association.rb @@ -9,8 +9,6 @@ def self.included(klass) def construct_sql_with_group_scope if @reflection.options[:grouped_scope] - # CHANGED [Rails 1.2.6] Account for quoted_table_name. - table_name = @reflection.respond_to?(:quoted_table_name) ? @reflection.quoted_table_name : @reflection.klass.table_name if @reflection.options[:as] # TODO: Need to add case for polymorphic :as option. else diff --git a/test/grouped_scope/association_reflection_test.rb b/test/grouped_scope/association_reflection_test.rb index 3c3fa61..bc4227b 100644 --- a/test/grouped_scope/association_reflection_test.rb +++ b/test/grouped_scope/association_reflection_test.rb @@ -40,8 +40,6 @@ def setup should 'delegate instance methods to #ungrouped_reflection' do methods = [:class_name,:klass,:table_name,:primary_key_name,:active_record, :association_foreign_key,:counter_cache_column,:source_reflection] - # CHANGED [Rails 1.2.6] Account for quoted_table_name. - methods << :quoted_table_name if @ungrouped_reflection.respond_to?(:quoted_table_name) methods.each do |m| assert_equal @ungrouped_reflection.send(m), @grouped_reflection.send(m), "The method #{m.inspect} does not appear to be proxied to the ungrouped reflection." @@ -54,17 +52,11 @@ def setup end should 'derive class name to same as ungrouped reflection' do - # CHANGED [Rails 1.2.6] Account for quoted_table_name. - if @ungrouped_reflection.respond_to?(:derive_class_name) - assert_equal @ungrouped_reflection.send(:derive_class_name), @grouped_reflection.send(:derive_class_name) - end + assert_equal @ungrouped_reflection.send(:derive_class_name), @grouped_reflection.send(:derive_class_name) end should 'derive primary key name to same as ungrouped reflection' do - # CHANGED [Rails 1.2.6] Account for quoted_table_name. - if @ungrouped_reflection.respond_to?(:derive_primary_key_name) - assert_equal @ungrouped_reflection.send(:derive_primary_key_name), @grouped_reflection.send(:derive_primary_key_name) - end + assert_equal @ungrouped_reflection.send(:derive_primary_key_name), @grouped_reflection.send(:derive_primary_key_name) end should 'honor explicit legacy reports association options like class_name and foreign_key' do diff --git a/test/lib/boot.rb b/test/lib/boot.rb index 00c21c8..689ab96 100644 --- a/test/lib/boot.rb +++ b/test/lib/boot.rb @@ -28,5 +28,4 @@ gem 'mislav-will_paginate', '2.3.4' require 'will_paginate' WillPaginate.enable_activerecord -require 'named_scope' diff --git a/test/lib/core_ext.rb b/test/lib/core_ext.rb deleted file mode 100644 index 8b64ba7..0000000 --- a/test/lib/core_ext.rb +++ /dev/null @@ -1,20 +0,0 @@ - -unless Hash.instance_methods.include? 'except' - - Hash.class_eval do - - # Returns a new hash without the given keys. - def except(*keys) - rejected = Set.new(respond_to?(:convert_key) ? keys.map { |key| convert_key(key) } : keys) - reject { |key,| rejected.include?(key) } - end - - # Replaces the hash without only the given keys. - def except!(*keys) - replace(except(*keys)) - end - - end - -end - diff --git a/test/lib/named_scope.rb b/test/lib/named_scope.rb deleted file mode 100755 index 589dae3..0000000 --- a/test/lib/named_scope.rb +++ /dev/null @@ -1,7 +0,0 @@ -unless defined? ActiveRecord::NamedScope - require "named_scope/core_ext" - require "named_scope/named_scope" - require "named_scope/named_scope_patch_#{ActiveRecord::Base.respond_to?(:find_first) ? '1.2' : '2.0'}" - ActiveRecord::Base.send :include, ActiveRecord::NamedScope -end - diff --git a/test/lib/named_scope/core_ext.rb b/test/lib/named_scope/core_ext.rb deleted file mode 100755 index 10b4410..0000000 --- a/test/lib/named_scope/core_ext.rb +++ /dev/null @@ -1,82 +0,0 @@ - -unless Hash.instance_methods.include? 'except' - Hash.class_eval do - - # Returns a new hash without the given keys. - def except(*keys) - rejected = Set.new(respond_to?(:convert_key) ? keys.map { |key| convert_key(key) } : keys) - reject { |key,| rejected.include?(key) } - end - - # Replaces the hash without only the given keys. - def except!(*keys) - replace(except(*keys)) - end - - end -end - -class ActiveRecord::Base - class << self - - def first(*args) - find(:first, *args) - end - - def last(*args) - find(:last, *args) - end - - def all(*args) - find(:all, *args) - end - - private - - def find_last(options) - order = options[:order] - if order - order = reverse_sql_order(order) - elsif !scoped?(:find, :order) - order = "#{table_name}.#{primary_key} DESC" - end - if scoped?(:find, :order) - scoped_order = reverse_sql_order(scope(:find, :order)) - scoped_methods.select { |s| s[:find].update(:order => scoped_order) } - end - find_initial(options.merge({ :order => order })) - end - - def reverse_sql_order(order_query) - reversed_query = order_query.split(/,/).each { |s| - if s.match(/\s(asc|ASC)$/) - s.gsub!(/\s(asc|ASC)$/, ' DESC') - elsif s.match(/\s(desc|DESC)$/) - s.gsub!(/\s(desc|DESC)$/, ' ASC') - elsif !s.match(/\s(asc|ASC|desc|DESC)$/) - s.concat(' DESC') - end - }.join(',') - end - - end -end - -ActiveRecord::Associations::AssociationCollection.class_eval do - - def last(*args) - if fetch_first_or_last_using_find? args - find(:last, *args) - else - load_target unless loaded? - @target.last(*args) - end - end - - private - - def fetch_first_or_last_using_find?(args) - args.first.kind_of?(Hash) || !(loaded? || @owner.new_record? || @reflection.options[:finder_sql] || !@target.blank? || args.first.kind_of?(Integer)) - end - -end diff --git a/test/lib/named_scope/named_scope.rb b/test/lib/named_scope/named_scope.rb deleted file mode 100755 index b30ef97..0000000 --- a/test/lib/named_scope/named_scope.rb +++ /dev/null @@ -1,168 +0,0 @@ -module ActiveRecord - module NamedScope - # All subclasses of ActiveRecord::Base have two named_scopes: - # * all, which is similar to a find(:all) query, and - # * scoped, which allows for the creation of anonymous scopes, on the fly: Shirt.scoped(:conditions => {:color => 'red'}).scoped(:include => :washing_instructions) - # - # These anonymous scopes tend to be useful when procedurally generating complex queries, where passing - # intermediate values (scopes) around as first-class objects is convenient. - def self.included(base) - base.class_eval do - extend ClassMethods - named_scope :scoped, lambda { |scope| scope } - end - end - - module ClassMethods - def scopes - read_inheritable_attribute(:scopes) || write_inheritable_attribute(:scopes, {}) - end - - # Adds a class method for retrieving and querying objects. A scope represents a narrowing of a database query, - # such as :conditions => {:color => :red}, :select => 'shirts.*', :include => :washing_instructions. - # - # class Shirt < ActiveRecord::Base - # named_scope :red, :conditions => {:color => 'red'} - # named_scope :dry_clean_only, :joins => :washing_instructions, :conditions => ['washing_instructions.dry_clean_only = ?', true] - # end - # - # The above calls to named_scope define class methods Shirt.red and Shirt.dry_clean_only. Shirt.red, - # in effect, represents the query Shirt.find(:all, :conditions => {:color => 'red'}). - # - # 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.find(:first), Shirt.red.count, - # Shirt.red.find(:all, :conditions => {:size => 'small'}). Also, just - # as with the association objects, name scopes acts like an Array, implementing Enumerable; Shirt.red.each(&block), - # Shirt.red.first, and Shirt.red.inject(memo, &block) all behave as if Shirt.red really were an Array. - # - # These named scopes are composable. For instance, Shirt.red.dry_clean_only will produce all shirts that are both red and dry clean only. - # Nested finds and calculations also work with these compositions: Shirt.red.dry_clean_only.count returns the number of garments - # for which these criteria obtain. Similarly with Shirt.red.dry_clean_only.average(:thread_count). - # - # All scopes are available as class methods on the ActiveRecord::Base descendent upon which the scopes were defined. But they are also available to - # has_many associations. If, - # - # class Person < ActiveRecord::Base - # has_many :shirts - # end - # - # then elton.shirts.red.dry_clean_only will return all of Elton's red, dry clean - # only shirts. - # - # Named scopes can also be procedural. - # - # class Shirt < ActiveRecord::Base - # named_scope :colored, lambda { |color| - # { :conditions => { :color => color } } - # } - # end - # - # In this example, Shirt.colored('puce') finds all puce shirts. - # - # Named scopes can also have extensions, just as with has_many declarations: - # - # class Shirt < ActiveRecord::Base - # named_scope :red, :conditions => {:color => 'red'} do - # def dom_id - # 'red_shirts' - # end - # end - # end - # - # - # For testing complex named scopes, you can examine the scoping options using the - # proxy_options method on the proxy itself. - # - # class Shirt < ActiveRecord::Base - # named_scope :colored, lambda { |color| - # { :conditions => { :color => color } } - # } - # end - # - # expected_options = { :conditions => { :colored => 'red' } } - # assert_equal expected_options, Shirt.colored('red').proxy_options - def named_scope(name, options = {}, &block) - name = name.to_sym - scopes[name] = lambda do |parent_scope, *args| - Scope.new(parent_scope, case options - when Hash - options - when Proc - options.call(*args) - end, &block) - end - (class << self; self end).instance_eval do - define_method name do |*args| - scopes[name].call(self, *args) - end - end - end - end - - class Scope - attr_reader :proxy_scope, :proxy_options - - [].methods.each do |m| - unless m =~ /(^__|^nil\?|^send|^object_id$|class|extend|^find$|count|sum|average|maximum|minimum|paginate|first|last|empty\?|respond_to\?)/ - delegate m, :to => :proxy_found - end - end - - delegate :scopes, :with_scope, :to => :proxy_scope - - def initialize(proxy_scope, options, &block) - [options[:extend]].flatten.each { |extension| extend extension } if options[:extend] - extend Module.new(&block) if block_given? - @proxy_scope, @proxy_options = proxy_scope, options.except(:extend) - end - - def reload - load_found; self - end - - def first(*args) - if args.first.kind_of?(Integer) || (@found && !args.first.kind_of?(Hash)) - proxy_found.first(*args) - else - find(:first, *args) - end - end - - def last(*args) - if args.first.kind_of?(Integer) || (@found && !args.first.kind_of?(Hash)) - proxy_found.last(*args) - else - find(:last, *args) - end - end - - def empty? - @found ? @found.empty? : count.zero? - end - - def respond_to?(method, include_private = false) - super || @proxy_scope.respond_to?(method, include_private) - end - - protected - def proxy_found - @found || load_found - end - - private - def method_missing(method, *args, &block) - if scopes.include?(method) - scopes[method].call(self, *args) - else - with_scope :find => proxy_options do - proxy_scope.send(method, *args, &block) - end - end - end - - def load_found - @found = find(:all) - end - end - end -end diff --git a/test/lib/named_scope/named_scope_patch_1.2.rb b/test/lib/named_scope/named_scope_patch_1.2.rb deleted file mode 100755 index 01fc507..0000000 --- a/test/lib/named_scope/named_scope_patch_1.2.rb +++ /dev/null @@ -1,85 +0,0 @@ - -ActiveRecord::Associations::AssociationProxy.class_eval do - protected - def with_scope(*args, &block) - @reflection.klass.send :with_scope, *args, &block - end -end - -class ActiveRecord::Base - class << self - def find(*args) - options = extract_options_from_args!(args) - validate_find_options(options) - set_readonly_option!(options) - case args.first - when :first then find_initial(options) - when :last then find_last(options) - when :all then find_every(options) - else find_from_ids(args, options) - end - end - private - def attribute_condition_with_named_scope(argument) - case argument - when ActiveRecord::Associations::AssociationCollection, ActiveRecord::NamedScope::Scope then "IN (?)" - else attribute_condition_without_named_scope(argument) - end - end - alias_method_chain :attribute_condition, :named_scope - end -end - -ActiveRecord::Associations::HasManyAssociation.class_eval do - protected - def method_missing(method, *args, &block) - if @target.respond_to?(method) || (!@reflection.klass.respond_to?(method) && Class.respond_to?(method)) - super - elsif @reflection.klass.scopes.include?(method) - @reflection.klass.scopes[method].call(self, *args) - else - create_scoping = {} - set_belongs_to_association_for(create_scoping) - - @reflection.klass.with_scope( - :create => create_scoping, - :find => { - :conditions => @finder_sql, - :joins => @join_sql, - :readonly => false - } - ) do - @reflection.klass.send(method, *args, &block) - end - end - end -end - -ActiveRecord::Associations::HasManyThroughAssociation.class_eval do - protected - def method_missing(method, *args, &block) - if @target.respond_to?(method) || (!@reflection.klass.respond_to?(method) && Class.respond_to?(method)) - super - elsif @reflection.klass.scopes.include?(method) - @reflection.klass.scopes[method].call(self, *args) - else - @reflection.klass.with_scope(construct_scope) { @reflection.klass.send(method, *args, &block) } - end - end -end - -ActiveRecord::Associations::HasAndBelongsToManyAssociation.class_eval do - protected - def method_missing(method, *args, &block) - if @target.respond_to?(method) || (!@reflection.klass.respond_to?(method) && Class.respond_to?(method)) - super - elsif @reflection.klass.scopes.include?(method) - @reflection.klass.scopes[method].call(self, *args) - else - @reflection.klass.with_scope(:find => { :conditions => @finder_sql, :joins => @join_sql, :readonly => false }) do - @reflection.klass.send(method, *args, &block) - end - end - end -end - diff --git a/test/lib/named_scope/named_scope_patch_2.0.rb b/test/lib/named_scope/named_scope_patch_2.0.rb deleted file mode 100755 index ae780c2..0000000 --- a/test/lib/named_scope/named_scope_patch_2.0.rb +++ /dev/null @@ -1,55 +0,0 @@ - -ActiveRecord::Associations::AssociationProxy.class_eval do - protected - def with_scope(*args, &block) - @reflection.klass.send :with_scope, *args, &block - end -end - -class ActiveRecord::Base - class << self - def find(*args) - options = args.extract_options! - validate_find_options(options) - set_readonly_option!(options) - case args.first - when :first then find_initial(options) - when :last then find_last(options) - when :all then find_every(options) - else find_from_ids(args, options) - end - end - private - def attribute_condition_with_named_scope(argument) - case argument - when ActiveRecord::NamedScope::Scope then "IN (?)" - else attribute_condition_without_named_scope(argument) - end - end - alias_method_chain :attribute_condition, :named_scope - end -end - -ActiveRecord::Associations::AssociationCollection.class_eval do - protected - def method_missing(method, *args) - if @target.respond_to?(method) || (!@reflection.klass.respond_to?(method) && Class.respond_to?(method)) - if block_given? - super { |*block_args| yield(*block_args) } - else - super - end - elsif @reflection.klass.scopes.include?(method) - @reflection.klass.scopes[method].call(self, *args) - else - with_scope(construct_scope) do - if block_given? - @reflection.klass.send(method, *args) { |*block_args| yield(*block_args) } - else - @reflection.klass.send(method, *args) - end - end - end - end -end -