From 548c82ef9bcdcedcd60423d06e425cf9662d0b66 Mon Sep 17 00:00:00 2001 From: Ken Collins Date: Sun, 4 Dec 2011 16:08:29 -0500 Subject: [PATCH] Almost there. --- README.md | 1 - TODO | 22 +++ lib/grouped_scope.rb | 7 +- .../arish/associations/association_scope.rb | 136 ++++++++++++++++-- ...e.rb => grouped_collection_association.rb} | 20 ++- .../associations/collection_association.rb | 8 +- lib/grouped_scope/arish/base.rb | 6 +- .../arish/relation/predicate_builer.rb | 27 ++++ lib/grouped_scope/self_grouping.rb | 16 +-- .../association_reflection_test.rb | 69 --------- test/grouped_scope/class_methods_test.rb | 47 ------ ...y_association_test.rb => has_many_test.rb} | 18 +-- .../has_many_through_association_test.rb | 50 ------- test/grouped_scope/has_many_through_test.rb | 51 +++++++ test/grouped_scope/reflection_test.rb | 62 ++++++++ test/helper.rb | 39 +++-- 16 files changed, 351 insertions(+), 228 deletions(-) rename lib/grouped_scope/arish/associations/builder/{grouped_scope.rb => grouped_collection_association.rb} (62%) create mode 100644 lib/grouped_scope/arish/relation/predicate_builer.rb delete mode 100644 test/grouped_scope/association_reflection_test.rb delete mode 100644 test/grouped_scope/class_methods_test.rb rename test/grouped_scope/{has_many_association_test.rb => has_many_test.rb} (86%) delete mode 100644 test/grouped_scope/has_many_through_association_test.rb create mode 100644 test/grouped_scope/has_many_through_test.rb create mode 100644 test/grouped_scope/reflection_test.rb diff --git a/README.md b/README.md index 26e73b5..d3df717 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,6 @@ defined on the original has_many. For instance: ## Todo List -* Add more GroupedScope::Grouping code. * Add polymorphic support. * Add :through support. * Raise errors and/or support :finder_sql/:counter_sql. diff --git a/TODO b/TODO index 23cf265..a238f2b 100644 --- a/TODO +++ b/TODO @@ -13,6 +13,21 @@ Notes: + + >> User.reflections[:columns].primary_key_column + => # + >> User.reflections[:columns].association_foreign_key + => "column_id" + >> User.reflections[:columns].association_primary_key + => "id" + >> User.reflections[:columns].active_record_primary_key + => "id" + >> User.reflections[:columns].active_record + => User(14 columns) + + + + equalities = wheres.grep(Arel::Nodes::Equality) >> ActiveRecord::Associations::AssociationScope.new(User.first.association(:columns)).scope.where_values @@ -62,3 +77,10 @@ https://github.com/thoughtbot/appraisal * Redo for rails 3.1 tests. + +* Kill &block stuff. + + + + + diff --git a/lib/grouped_scope.rb b/lib/grouped_scope.rb index 3fc658e..d337040 100644 --- a/lib/grouped_scope.rb +++ b/lib/grouped_scope.rb @@ -1,9 +1,10 @@ require 'active_record/version' require 'grouped_scope/errors' -require 'grouped_scope/grouping' require 'grouped_scope/self_grouping' -require 'grouped_scope/arish/associations/association_scope' +require 'grouped_scope/arish/reflection' require 'grouped_scope/arish/associations/collection_association' +require 'grouped_scope/arish/associations/builder/grouped_collection_association' +require 'grouped_scope/arish/associations/association_scope' +require 'grouped_scope/arish/relation/predicate_builer' require 'grouped_scope/arish/base' - diff --git a/lib/grouped_scope/arish/associations/association_scope.rb b/lib/grouped_scope/arish/associations/association_scope.rb index 26ab810..22055b4 100644 --- a/lib/grouped_scope/arish/associations/association_scope.rb +++ b/lib/grouped_scope/arish/associations/association_scope.rb @@ -3,22 +3,140 @@ module Arish module Associations class AssociationScope < ActiveRecord::Associations::AssociationScope - private def add_constraints(scope) - super(scope).tap do |s| - case reflection.macro - when :has_many - - # s.where_values - # [#, name="user_id">, @right=8>] - - end if reflection.grouped_scope? + tables = construct_tables + + chain.each_with_index do |reflection, i| + table, foreign_table = tables.shift, tables.first + + if reflection.source_macro == :has_and_belongs_to_many + join_table = tables.shift + + scope = scope.joins(join( + join_table, + table[reflection.association_primary_key]. + in(join_table[reflection.association_foreign_key]) + )) + + table, foreign_table = join_table, tables.first + end + + if reflection.source_macro == :belongs_to + if reflection.options[:polymorphic] + key = reflection.association_primary_key(klass) + else + key = reflection.association_primary_key + end + + foreign_key = reflection.foreign_key + else + key = reflection.foreign_key + foreign_key = reflection.active_record_primary_key + end + + conditions = self.conditions[i] + + if reflection == chain.last + # GroupedScope changed this line. + # scope = scope.where(table[key].eq(owner[foreign_key])) + scope = scope.where(table[key].in(owner.group.ids)) + + if reflection.type + scope = scope.where(table[reflection.type].eq(owner.class.base_class.name)) + end + + conditions.each do |condition| + if options[:through] && condition.is_a?(Hash) + condition = { table.name => condition } + end + + scope = scope.where(interpolate(condition)) + end + else + # GroupedScope changed this line. + # constraint = table[key].eq(foreign_table[foreign_key]) + constraint = table[key].in(owner.group.ids) + + if reflection.type + type = chain[i + 1].klass.base_class.name + constraint = constraint.and(table[reflection.type].eq(type)) + end + + scope = scope.joins(join(foreign_table, constraint)) + + unless conditions.empty? + scope = scope.where(sanitize(conditions, table)) + end + end end + + scope end end end end end + +=begin + +# Initial #add_constraints Idea +# ----------------------------- + +super(scope).tap do |s| + case reflection.macro + when :has_many + ... + end if reflection.grouped_scope? +end + + +# Simple AssociationScope Methods +# ------------------------------- + +as = ActiveRecord::Associations::AssociationScope.new(User.first.association(:columns)) ; as.object_id +as.klass # => Column(3 columns) +as.owner # => # +as.active_record # => User(14 columns) + + +# Reflection Stuff For Join Through +# --------------------------------- + +as.reflection +# => #"position", :extend=>[]}, @active_record=User(14 columns), @plural_name="columns", @collection=true, @class_name="Column", @klass=Column(3 columns), @foreign_key="user_id", @active_record_primary_key="id", @type=nil> + +as.reflection.association_primary_key # => "id" +as.reflection.association_foreign_key # => "column_id" + + +# How Tables Work In #add_constraints +# ----------------------------------- + +tables = as.send(:construct_tables) +table = tables.first + +key = as.reflection.foreign_key # => "user_id" +foreign_key = as.reflection.active_record_primary_key # => "id" + +table[key].eq(as.owner[foreign_key]).to_sql # => "columns"."user_id" = 8 +table[key].in([1,2,3]).to_sql # => "columns"."user_id" IN (1, 2, 3) +table[key].in(as.owner.group.ids).to_sql # => + + + + + +s = as.scope ; s.object_id +equalities = s.where_values.grep(Arel::Nodes::Equality) + +e = equalities.first +# => #, name="user_id">, @right=8> + + + + + +=end diff --git a/lib/grouped_scope/arish/associations/builder/grouped_scope.rb b/lib/grouped_scope/arish/associations/builder/grouped_collection_association.rb similarity index 62% rename from lib/grouped_scope/arish/associations/builder/grouped_scope.rb rename to lib/grouped_scope/arish/associations/builder/grouped_collection_association.rb index bbd1d05..64fe2e7 100644 --- a/lib/grouped_scope/arish/associations/builder/grouped_scope.rb +++ b/lib/grouped_scope/arish/associations/builder/grouped_collection_association.rb @@ -2,22 +2,24 @@ module GroupedScope module Arish module Associations module Builder - class GroupedScope + class GroupedCollectionAssociation class << self - def build(model, *associations) + def build(model, *association_names) association_names.each do |name| ungrouped_reflection = find_ungrouped_reflection(model, name) - grouped_reflection = model.send ungrouped_reflection.macro, :"grouped_scope_#{name}", ungrouped_reflection.options + options = ungrouped_reflection_options(ungrouped_reflection) + grouped_reflection = model.send ungrouped_reflection.macro, :"grouped_scope_#{name}", options grouped_reflection.grouped_scope = true + model.grouped_reflections = model.grouped_reflections.merge(name => grouped_reflection) end - define_grouped_scope_reader + define_grouped_scope_reader(model) end private - def define_grouped_scope_reader + def define_grouped_scope_reader(model) model.send(:define_method, :group) do @group ||= GroupedScope::SelfGroupping.new(self) end @@ -26,13 +28,19 @@ def define_grouped_scope_reader def find_ungrouped_reflection(model, name) reflection = model.reflections[name.to_sym] if reflection.blank? || [:has_many, :has_and_belongs_to_many].exclude?(reflection.macro) - msg = "Cannot create a group scope for #{name.inspect}. Either the reflection is blank or not supported." + + msg = "Cannot create a group scope for #{name.inspect}. Either the reflection is blank or not supported. " + "Make sure to call grouped_scope after the association you are trying to extend has been defined." raise ArgumentError, msg end reflection end + def ungrouped_reflection_options(ungrouped_reflection) + ungrouped_reflection.options.dup.tap do |options| + options[:class_name] = ungrouped_reflection.class_name + end + end + end end diff --git a/lib/grouped_scope/arish/associations/collection_association.rb b/lib/grouped_scope/arish/associations/collection_association.rb index 98215ca..57cdb2b 100644 --- a/lib/grouped_scope/arish/associations/collection_association.rb +++ b/lib/grouped_scope/arish/associations/collection_association.rb @@ -6,10 +6,12 @@ module CollectionAssociation extend ActiveSupport::Concern module InstanceMethods - + def association_scope - if klass - @association_scope ||= GroupedScope::Associations::AssociationScope.new(self).scope + if reflection.grouped_scope? + @association_scope ||= GroupedScope::Arish::Associations::AssociationScope.new(self).scope if klass + else + super end end diff --git a/lib/grouped_scope/arish/base.rb b/lib/grouped_scope/arish/base.rb index 7d26625..886081a 100644 --- a/lib/grouped_scope/arish/base.rb +++ b/lib/grouped_scope/arish/base.rb @@ -5,14 +5,14 @@ module Base extend ActiveSupport::Concern included do - class_attribute :grouped_scopes, :instance_reader => false, :instance_writer => false - self.grouped_scopes = {} + class_attribute :grouped_reflections, :instance_reader => false, :instance_writer => false + self.grouped_reflections = {}.freeze end module ClassMethods def grouped_scope(*association_names) - GroupedScope::Arish::Associations::Builder::GroupedScope.build(self, *association_names) + GroupedScope::Arish::Associations::Builder::GroupedCollectionAssociation.build(self, *association_names) end end diff --git a/lib/grouped_scope/arish/relation/predicate_builer.rb b/lib/grouped_scope/arish/relation/predicate_builer.rb new file mode 100644 index 0000000..ca0d44d --- /dev/null +++ b/lib/grouped_scope/arish/relation/predicate_builer.rb @@ -0,0 +1,27 @@ +module GroupedScope + module Arish + module PredicateBuilder + + extend ActiveSupport::Concern + + included do + singleton_class.alias_method_chain :build_from_hash, :grouped_scope + end + + module ClassMethods + + def build_from_hash_with_grouped_scope(engine, attributes, default_table) + attributes.select{ |k,v| GroupedScope::SelfGroupping === v }.each do |kv| + k, v = kv + attributes[k] = v.ids + end + build_from_hash_without_grouped_scope(engine, attributes, default_table) + end + + end + + end + end +end + +ActiveRecord::PredicateBuilder.send :include, GroupedScope::Arish::PredicateBuilder diff --git a/lib/grouped_scope/self_grouping.rb b/lib/grouped_scope/self_grouping.rb index 6c81a60..bf43ceb 100644 --- a/lib/grouped_scope/self_grouping.rb +++ b/lib/grouped_scope/self_grouping.rb @@ -26,7 +26,7 @@ def quoted_ids end def respond_to?(method, include_private=false) - super || !proxy_class.grouped_scopes[method].blank? + super || proxy_class.grouped_reflections[method].present? end @@ -36,12 +36,12 @@ def group_proxy @group_proxy ||= find_selves(group_scope_options) end - def all_grouped? - proxy_owner.all_grouped? rescue false + def grouped? + proxy_owner.group_id.present? end - def no_group? - proxy_owner.group_id.blank? + def all_grouped? + proxy_owner.all_grouped? rescue false end def find_selves(options={}) @@ -50,7 +50,7 @@ def find_selves(options={}) def group_scope_options return {} if all_grouped? - conditions = no_group? ? { primary_key => proxy_owner.id } : { :group_id => proxy_owner.group_id } + conditions = grouped? ? { :group_id => proxy_owner.group_id } : { primary_key => proxy_owner.id } { :conditions => conditions } end @@ -66,8 +66,8 @@ def proxy_class private def method_missing(method, *args, &block) - if proxy_class.grouped_scopes[method] - proxy_owner.send("grouped_scope_#{method}", *args, &block) + if proxy_class.grouped_reflections[method] + proxy_owner.send :"grouped_scope_#{method}", *args, &block else super end diff --git a/test/grouped_scope/association_reflection_test.rb b/test/grouped_scope/association_reflection_test.rb deleted file mode 100644 index 232a7bf..0000000 --- a/test/grouped_scope/association_reflection_test.rb +++ /dev/null @@ -1,69 +0,0 @@ -require 'helper' - -class GroupedScope::AssociationReflectionTest < GroupedScope::TestCase - - describe 'For initialization' do - - describe 'Raise and exception' do - - before { @reflection_klass = GroupedScope::AssociationReflection } - - it 'when a association does not exist' do - lambda{ @reflection_klass.new(Employee,:doesnotexist) }.must_raise(ArgumentError) - end - - it 'when the association is not a has_many or a has_and_belongs_to_many' do - Employee.class_eval { belongs_to(:foo) } - lambda{ @reflection_klass.new(Employee,:foo) }.must_raise(ArgumentError) - end - - end - - end - - describe 'For #ungrouped_reflection' do - - before do - @ungrouped_reflection = Employee.reflections[:reports] - @grouped_reflection = Employee.reflections[:grouped_scope_reports] - end - - it 'access ungrouped reflection' do - assert_equal @ungrouped_reflection, @grouped_reflection.ungrouped_reflection - end - - it '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] - 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." - end - end - - it 'not delegate to #ungrouped_reflection for #options and #name' do - @ungrouped_reflection.name.wont_equal @grouped_reflection.name - @ungrouped_reflection.options.wont_equal @grouped_reflection.options - end - - it 'derive class name to same as ungrouped reflection' do - assert_equal @ungrouped_reflection.send(:derive_class_name), @grouped_reflection.send(:derive_class_name) - end - - it 'derive primary key name to same as ungrouped reflection' do - assert_equal @ungrouped_reflection.send(:derive_primary_key_name), @grouped_reflection.send(:derive_primary_key_name) - end - - it 'honor explicit legacy reports association options like class_name and foreign_key' do - @ungrouped_reflection = LegacyEmployee.reflections[:reports] - @grouped_reflection = LegacyEmployee.reflections[:grouped_scope_reports] - [:class_name,:primary_key_name].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." - end - end - - end - - -end diff --git a/test/grouped_scope/class_methods_test.rb b/test/grouped_scope/class_methods_test.rb deleted file mode 100644 index e0b0147..0000000 --- a/test/grouped_scope/class_methods_test.rb +++ /dev/null @@ -1,47 +0,0 @@ -require 'helper' - -class GroupedScope::ClassMethodsTest < GroupedScope::TestCase - - describe 'For .grouped_scopes' do - - it 'have a inheritable attribute hash' do - assert_instance_of Hash, Employee.grouped_scopes - end - - it 'add to inheritable attributes with new grouped_scope' do - Employee.grouped_scopes[:foobars] = nil - Employee.class_eval { has_many(:foobars) ; grouped_scope(:foobars) } - assert Employee.grouped_scopes[:foobars] - end - - end - - describe 'For .grouped_scope' do - - it 'create a belongs_to :grouping association' do - assert Employee.reflections[:grouping] - end - - it 'not recreate belongs_to :grouping on additional calls' do - Employee.expects(:belongs_to).never - Employee.class_eval { has_many(:foobars) ; grouped_scope(:foobars) } - end - - it 'create a has_many assoc named :grouped_scope_* using existing association as a suffix' do - grouped_reports_assoc = Employee.reflections[:grouped_scope_reports] - assert_instance_of GroupedScope::AssociationReflection, grouped_reports_assoc - assert FactoryGirl.create(:employee).respond_to?(:grouped_scope_reports) - end - - it 'not add the :grouped_scope option to existing reflection' do - assert_nil Employee.reflections[:reports].options[:grouped_scope] - end - - it 'have added the :grouped_scope option to new grouped reflection' do - assert Employee.reflections[:grouped_scope_reports].options[:grouped_scope] - end - - end - - -end diff --git a/test/grouped_scope/has_many_association_test.rb b/test/grouped_scope/has_many_test.rb similarity index 86% rename from test/grouped_scope/has_many_association_test.rb rename to test/grouped_scope/has_many_test.rb index a8c489f..6c3372b 100644 --- a/test/grouped_scope/has_many_association_test.rb +++ b/test/grouped_scope/has_many_test.rb @@ -1,6 +1,6 @@ require 'helper' -class GroupedScope::HasManyAssociationTest < GroupedScope::TestCase +class GroupedScope::HasManyTest < GroupedScope::TestCase describe 'For an Employee' do @@ -9,13 +9,13 @@ class GroupedScope::HasManyAssociationTest < GroupedScope::TestCase end it 'scope existing association to owner' do - assert_sql(/employee_id = #{@employee.id}/) do + assert_sql(/"employee_id" = #{@employee.id}/) do @employee.reports(true) end end it 'scope group association to group' do - assert_sql(/employee_id IN \(#{@employee.id}\)/) do + assert_sql(/"employee_id" IN \(#{@employee.id}\)/) do @employee.group.reports(true) end end @@ -28,13 +28,13 @@ class GroupedScope::HasManyAssociationTest < GroupedScope::TestCase end it 'scope count sql to owner' do - assert_sql(/SELECT count\(\*\)/,/employee_id = #{@e1.id}/) do + assert_sql(/SELECT COUNT\(\*\)/,/"employee_id" = #{@e1.id}/) do @e1.reports(true).count end end it 'scope count sql to group' do - assert_sql(/SELECT count\(\*\)/,/employee_id IN \(#{@e1.id},#{@e2.id}\)/) do + assert_sql(/SELECT COUNT\(\*\)/,/"employee_id" IN \(#{@e1.id}, #{@e2.id}\)/) do @e1.group.reports(true).count end end @@ -105,13 +105,13 @@ class GroupedScope::HasManyAssociationTest < GroupedScope::TestCase end it 'scope existing association to owner' do - assert_sql(/"?legacy_reports"?.email = '#{@employee.id}'/) do + assert_sql(/"legacy_reports"."email" = '#{@employee.id}'/) do @employee.reports(true) end end it 'scope group association to group' do - assert_sql(/"?legacy_reports"?.email IN \('#{@employee.id}'\)/) do + assert_sql(/"legacy_reports"."email" IN \('#{@employee.id}'\)/) do @employee.group.reports(true) end end @@ -122,11 +122,11 @@ class GroupedScope::HasManyAssociationTest < GroupedScope::TestCase protected def select_from_reports - /SELECT \* FROM "?reports"?/ + /SELECT "reports"\.\* FROM "reports"/ end def where_for_groups - /WHERE.*"?reports"?.employee_id IN \(2,3\)/ + /WHERE "reports"."employee_id" IN \(2, 3\)/ end def where_for_urgent_body diff --git a/test/grouped_scope/has_many_through_association_test.rb b/test/grouped_scope/has_many_through_association_test.rb deleted file mode 100644 index c061344..0000000 --- a/test/grouped_scope/has_many_through_association_test.rb +++ /dev/null @@ -1,50 +0,0 @@ -# require 'helper' -# -# class GroupedScope::HasManyThroughAssociationTest < GroupedScope::TestCase -# -# before do -# @e1 = FactoryGirl.create(:employee, :group_id => 1) -# @e1.departments << Department.hr << Department.finance -# @e2 = FactoryGirl.create(:employee, :group_id => 1) -# @e2.departments << Department.it -# @all_group_departments = [Department.hr, Department.it, Department.finance] -# end -# -# describe 'For default association' do -# -# it 'scope to owner' do -# assert_sql(/employee_id = #{@e1.id}/) do -# @e1.departments(true) -# end -# end -# -# it 'scope count to owner' do -# assert_sql(/employee_id = #{@e1.id}/) do -# @e1.departments(true).count -# end -# end -# -# end -# -# describe 'For grouped association' do -# -# it 'scope to group' do -# assert_sql(/employee_id IN \(#{@e1.id},#{@e2.id}\)/) do -# @e2.group.departments(true) -# end -# end -# -# it 'scope count to group' do -# assert_sql(/employee_id IN \(#{@e1.id},#{@e2.id}\)/) do -# @e1.group.departments(true).count -# end -# end -# -# it 'have a group count equal to sum of seperate owner counts' do -# assert_equal @e1.departments(true).count + @e2.departments(true).count, @e2.group.departments(true).count -# end -# -# end -# -# -# end diff --git a/test/grouped_scope/has_many_through_test.rb b/test/grouped_scope/has_many_through_test.rb new file mode 100644 index 0000000..0270cb6 --- /dev/null +++ b/test/grouped_scope/has_many_through_test.rb @@ -0,0 +1,51 @@ +require 'helper' + +class GroupedScope::HasManyThroughTest < GroupedScope::TestCase + + before do + @e1 = FactoryGirl.create(:employee, :group_id => 1) + @e1.departments << Department.hr << Department.finance + @e2 = FactoryGirl.create(:employee, :group_id => 1) + @e2.departments << Department.it + @all_group_departments = [Department.hr, Department.it, Department.finance] + end + + describe 'For default association' do + + it 'scope to owner' do + assert_sql(/"employee_id" = #{@e1.id}/) do + @e1.departments(true) + end + end + + it 'scope count to owner' do + assert_sql(/"employee_id" = #{@e1.id}/) do + @e1.departments(true).count + end + end + + end + + describe 'For grouped association' do + + it 'scope to group' do + raise @e2.group.departments(true).inspect + assert_sql(/"employee_id" IN \(#{@e1.id}, #{@e2.id}\)/) do + @e2.group.departments(true) + end + end + + # it 'scope count to group' do + # assert_sql(/employee_id IN \(#{@e1.id},#{@e2.id}\)/) do + # @e1.group.departments(true).count + # end + # end + # + # it 'have a group count equal to sum of seperate owner counts' do + # assert_equal @e1.departments(true).count + @e2.departments(true).count, @e2.group.departments(true).count + # end + + end + + +end diff --git a/test/grouped_scope/reflection_test.rb b/test/grouped_scope/reflection_test.rb new file mode 100644 index 0000000..bb1b299 --- /dev/null +++ b/test/grouped_scope/reflection_test.rb @@ -0,0 +1,62 @@ +require 'helper' + +class GroupedScope::ReflectionTest < GroupedScope::TestCase + + it 'creates a has_many association named :grouped_scope_* using existing association as a suffix' do + assert FactoryGirl.create(:employee).respond_to?(:grouped_scope_reports) + end + + it 'does not add the #grouped_scope to existing reflection' do + assert_nil Employee.reflections[:reports].grouped_scope? + end + + it 'should have added the #grouped_scope to new grouped reflection' do + assert Employee.reflections[:grouped_scope_reports].grouped_scope? + end + + describe 'Class attribute for #grouped_reflections' do + + it 'should one' do + assert_instance_of Hash, Employee.grouped_reflections + end + + it 'populate with new grouped scopes' do + assert_nil Employee.grouped_reflections[:newgroupes] + Employee.class_eval { has_many(:newgroupes) ; grouped_scope(:newgroupes) } + assert Employee.grouped_reflections[:newgroupes] + end + + end + + describe 'Raise and exception' do + + it 'when a association does not exist' do + begin + raised = false + Employee.class_eval{ grouped_scope(:doesnotexist) } + rescue ArgumentError => e + raised = true + e.message.must_match %r{Cannot create a group scope for :doesnotexist} + ensure + assert raised, 'Did not raise an ArgumentError' + end + end + + it 'when the association is not a has_many or a has_and_belongs_to_many' do + begin + raised = false + Employee.class_eval { belongs_to(:belongstowillnotwork) ; grouped_scope(:belongstowillnotwork) } + rescue ArgumentError => e + raised = true + e.message.must_match %r{:belongstowillnotwork.*the reflection is blank or not supported} + ensure + assert raised, 'Did not raise an ArgumentError' + end + end + + end + + + + +end diff --git a/test/helper.rb b/test/helper.rb index 4bda528..74a22bb 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -13,7 +13,7 @@ module ActiveRecord class SQLCounter cattr_accessor :ignored_sql - self.ignored_sql = [/^PRAGMA (?!(table_info))/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/, /^SAVEPOINT/, /^ROLLBACK TO SAVEPOINT/, /^RELEASE SAVEPOINT/, /^SHOW max_identifier_length/, /^BEGIN/, /^COMMIT/] + self.ignored_sql = [/^PRAGMA table_info\(.*\)/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/, /^SAVEPOINT/, /^ROLLBACK TO SAVEPOINT/, /^RELEASE SAVEPOINT/, /^SHOW max_identifier_length/, /^BEGIN/, /^COMMIT/] ignored_sql.concat [/^select .*nextval/i, /^SAVEPOINT/, /^ROLLBACK TO/, /^\s*select .* from all_triggers/im] def initialize $queries_executed = [] @@ -121,13 +121,17 @@ def setup_database(options) end end - -class Employee < ActiveRecord::Base - has_many :reports do ; def urgent ; find(:all,:conditions => {:title => 'URGENT'}) ; end ; end - has_many :taxonomies, :as => :classable +class Department < ActiveRecord::Base + scope :it, where(:name => 'IT') + scope :hr, where(:name => 'Human Resources') + scope :finance, where(:name => 'Finance') has_many :department_memberships - has_many :departments, :through => :department_memberships - grouped_scope :reports, :departments + has_many :employees, :through => :department_memberships +end + +class DepartmentMembership < ActiveRecord::Base + belongs_to :employee + belongs_to :department end class Report < ActiveRecord::Base @@ -138,17 +142,16 @@ def urgent_title? ; self[:title] == 'URGENT' ; end def urgent_body? ; self[:body] =~ /URGENT/ ; end end -class Department < ActiveRecord::Base - scope :it, where(:name => 'IT') - scope :hr, where(:name => 'Human Resources') - scope :finance, where(:name => 'Finance') - has_many :department_memberships - has_many :employees, :through => :department_memberships +class LegacyReport < ActiveRecord::Base + belongs_to :employee, :class_name => 'LegacyEmployee', :foreign_key => 'email' end -class DepartmentMembership < ActiveRecord::Base - belongs_to :employee - belongs_to :department +class Employee < ActiveRecord::Base + has_many :reports do ; def urgent ; find(:all,:conditions => {:title => 'URGENT'}) ; end ; end + has_many :taxonomies, :as => :classable + has_many :department_memberships + has_many :departments, :through => :department_memberships + grouped_scope :reports, :departments end class LegacyEmployee < ActiveRecord::Base @@ -157,10 +160,6 @@ class LegacyEmployee < ActiveRecord::Base grouped_scope :reports end -class LegacyReport < ActiveRecord::Base - belongs_to :employee, :class_name => 'LegacyEmployee', :foreign_key => 'email' -end - class FooBar < ActiveRecord::Base has_many :reports grouped_scope :reports