From 5bb4cc3ba8a89318f773e3bc58c24a70801331b6 Mon Sep 17 00:00:00 2001 From: Ken Collins Date: Thu, 25 Sep 2008 20:23:11 -0400 Subject: [PATCH] Adding HasManyThroughAssociation support. --- README | 2 +- lib/grouped_scope.rb | 4 +- lib/grouped_scope/class_methods.rb | 2 + lib/grouped_scope/has_many_association.rb | 16 ++++-- .../has_many_through_association.rb | 28 +++++++++++ .../has_many_association_test.rb | 4 +- .../has_many_through_association_test.rb | 49 +++++++++++++++++++ 7 files changed, 96 insertions(+), 9 deletions(-) create mode 100644 lib/grouped_scope/has_many_through_association.rb create mode 100644 test/grouped_scope/has_many_through_association_test.rb diff --git a/README b/README index 308c5b9..54e7313 100644 --- a/README +++ b/README @@ -12,7 +12,7 @@ TODO * Change these to account for :as option: GroupedScope::HasManyAssociation * Turn on some mocha options/warnings. - +* Support finder sql Running Tests ============= diff --git a/lib/grouped_scope.rb b/lib/grouped_scope.rb index 6fc456d..5c1eaf2 100644 --- a/lib/grouped_scope.rb +++ b/lib/grouped_scope.rb @@ -4,6 +4,7 @@ require 'grouped_scope/association_reflection' require 'grouped_scope/class_methods' require 'grouped_scope/has_many_association' +require 'grouped_scope/has_many_through_association' module GroupedScope @@ -11,6 +12,3 @@ module GroupedScope end -ActiveRecord::Base.send :extend, GroupedScope::ClassMethods -ActiveRecord::Associations::HasManyAssociation.send :include, GroupedScope::HasManyAssociation - diff --git a/lib/grouped_scope/class_methods.rb b/lib/grouped_scope/class_methods.rb index 8936c5c..d791057 100644 --- a/lib/grouped_scope/class_methods.rb +++ b/lib/grouped_scope/class_methods.rb @@ -28,3 +28,5 @@ def create_belongs_to_for_grouped_scope end end + +ActiveRecord::Base.send :extend, GroupedScope::ClassMethods diff --git a/lib/grouped_scope/has_many_association.rb b/lib/grouped_scope/has_many_association.rb index 68ea7bd..32e3b71 100644 --- a/lib/grouped_scope/has_many_association.rb +++ b/lib/grouped_scope/has_many_association.rb @@ -6,17 +6,27 @@ def self.included(klass) alias_method_chain :construct_sql, :group_scope end end - + def construct_sql_with_group_scope if @reflection.options[:grouped_scope] - @finder_sql = "#{@reflection.quoted_table_name}.#{@reflection.primary_key_name} IN (#{@owner.group.quoted_ids})" - @finder_sql << " AND (#{conditions})" if conditions + if @reflection.options[:as] + # TODO: Need to add case for polymorphic :as option. + # @finder_sql = + # "#{@reflection.quoted_table_name}.#{@reflection.options[:as]}_id = #{@owner.quoted_id} AND " + + # "#{@reflection.quoted_table_name}.#{@reflection.options[:as]}_type = #{@owner.class.quote_value(@owner.class.base_class.name.to_s)}" + # @finder_sql << " AND (#{conditions})" if conditions + else + @finder_sql = "#{@reflection.quoted_table_name}.#{@reflection.primary_key_name} IN (#{@owner.group.quoted_ids})" + @finder_sql << " AND (#{conditions})" if conditions + end @counter_sql = @finder_sql else construct_sql_without_group_scope end end + end end +ActiveRecord::Associations::HasManyAssociation.send :include, GroupedScope::HasManyAssociation diff --git a/lib/grouped_scope/has_many_through_association.rb b/lib/grouped_scope/has_many_through_association.rb new file mode 100644 index 0000000..9b10b1c --- /dev/null +++ b/lib/grouped_scope/has_many_through_association.rb @@ -0,0 +1,28 @@ +module GroupedScope + module HasManyThroughAssociation + + def self.included(klass) + klass.class_eval do + alias_method_chain :construct_conditions, :group_scope + end + end + + def construct_conditions_with_group_scope + conditions = construct_conditions_without_group_scope + if @reflection.options[:grouped_scope] + if as = @reflection.options[:as] + # TODO: Need to add case for polymorphic :as option. + else + pattern = "#{@reflection.primary_key_name} = #{@owner.quoted_id}" + replacement = "#{@reflection.primary_key_name} IN (#{@owner.group.quoted_ids})" + conditions.sub!(pattern,replacement) + end + end + conditions + end + + + end +end + +ActiveRecord::Associations::HasManyThroughAssociation.send :include, GroupedScope::HasManyThroughAssociation diff --git a/test/grouped_scope/has_many_association_test.rb b/test/grouped_scope/has_many_association_test.rb index 82ee8d9..f415292 100644 --- a/test/grouped_scope/has_many_association_test.rb +++ b/test/grouped_scope/has_many_association_test.rb @@ -14,13 +14,13 @@ def setup end should 'scope existing association to owner' do - assert_sql(/"reports".employee_id = #{@employee.id}/) do + assert_sql(/employee_id = #{@employee.id}/) do @employee.reports(true) end end should 'scope group association to group' do - assert_sql(/"reports".employee_id IN \(#{@employee.id}\)/) do + assert_sql(/employee_id IN \(#{@employee.id}\)/) do @employee.group.reports(true) end end diff --git a/test/grouped_scope/has_many_through_association_test.rb b/test/grouped_scope/has_many_through_association_test.rb new file mode 100644 index 0000000..513efbe --- /dev/null +++ b/test/grouped_scope/has_many_through_association_test.rb @@ -0,0 +1,49 @@ +require File.dirname(__FILE__) + '/../helper' + +class HasManyThroughAssociationTest < GroupedScope::TestCase + + def setup + setup_environment + @e1 = Factory(:employee, :group_id => 1) + @e1.departments << Department.hr << Department.finance + @e2 = Factory(:employee, :group_id => 1) + @e2.departments << Department.it + @all_group_departments = [Department.hr, Department.it, Department.finance] + end + + + context 'For default association' do + + should 'scope to owner' do + assert_sql(/employee_id = #{@e1.id}/) do + @e1.departments(true) + end + end + + should 'scope count to owner' do + assert_sql(/employee_id = #{@e1.id}/) do + @e1.departments(true).count + end + end + + end + + context 'For grouped association' do + + should 'scope to group' do + assert_sql(/employee_id IN \(#{@e1.id},#{@e2.id}\)/) do + @e2.group.departments(true) + end + end + + should 'scope count to group' do + assert_sql(/employee_id IN \(#{@e1.id},#{@e2.id}\)/) do + @e1.group.departments(true).count + end + end + + end + + + +end