diff --git a/CHANGELOG b/CHANGELOG index 9871a07..9903801 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -7,6 +7,10 @@ * The group object is now an ActiveRecord::Relation so you can further scope it. +* New group scoped #blank? and #present? which simply checks if the proxy owner has a group set. + This allows us to tune the SQL generated to IN statements only when needed, even if a grouped + scope is being used. + * New group.ids_sql which is an Arel SQL literal. Avoids large groups IDs and better query plans. diff --git a/lib/grouped_scope/arish/associations/association_scope.rb b/lib/grouped_scope/arish/associations/association_scope.rb index d7d1448..b9057ec 100644 --- a/lib/grouped_scope/arish/associations/association_scope.rb +++ b/lib/grouped_scope/arish/associations/association_scope.rb @@ -48,7 +48,11 @@ def add_constraints(scope) 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)) + scope = if owner.group.present? + scope.where(table[key].in(owner.group.ids)) + else + scope.where(table[key].eq(owner[foreign_key])) + end if reflection.type scope = scope.where(table[reflection.type].eq(owner.class.base_class.name)) diff --git a/lib/grouped_scope/self_grouping.rb b/lib/grouped_scope/self_grouping.rb index 12630ee..1ac5469 100644 --- a/lib/grouped_scope/self_grouping.rb +++ b/lib/grouped_scope/self_grouping.rb @@ -17,6 +17,14 @@ def initialize(proxy_owner) @proxy_owner = proxy_owner end + def blank? + proxy_owner.group_id.blank? + end + + def present? + !blank? + end + def ids grouped_scoped_ids.map(&primary_key.to_sym) end @@ -64,17 +72,13 @@ def grouped_proxy @grouped_proxy ||= grouped_scoped end - def grouped? - proxy_owner.group_id.present? - end - def all_grouped? proxy_owner.all_grouped? rescue false end def grouped_scoped return proxy_class.scoped if all_grouped? - proxy_class.where grouped? ? arel_group_id.eq(proxy_owner.group_id) : arel_primary_key.eq(proxy_owner.id) + proxy_class.where present? ? arel_group_id.eq(proxy_owner.group_id) : arel_primary_key.eq(proxy_owner.id) end def grouped_scoped_ids diff --git a/test/grouped_scope/has_many_test.rb b/test/grouped_scope/has_many_test.rb index 6c3372b..f564e97 100644 --- a/test/grouped_scope/has_many_test.rb +++ b/test/grouped_scope/has_many_test.rb @@ -8,13 +8,20 @@ class GroupedScope::HasManyTest < GroupedScope::TestCase @employee = FactoryGirl.create(:employee) end - it 'scope existing association to owner' do + it 'scopes existing association to owner' do assert_sql(/"employee_id" = #{@employee.id}/) do @employee.reports(true) end end - it 'scope group association to group' do + it 'scopes group association to owner when no group present' do + assert_sql(/"employee_id" = #{@employee.id}/) do + @employee.group.reports(true) + end + end + + it 'scopes group association to owner when group present' do + @employee.update_attribute :group_id, 43 assert_sql(/"employee_id" IN \(#{@employee.id}\)/) do @employee.group.reports(true) end @@ -110,7 +117,14 @@ class GroupedScope::HasManyTest < GroupedScope::TestCase end end - it 'scope group association to group' do + it 'scope group association to owner, since no group is present' do + assert_sql(/"legacy_reports"."email" = '#{@employee.id}'/) do + @employee.group.reports(true) + end + end + + it 'scopes group association to owners group when present' do + @employee.update_attribute :group_id, 43 assert_sql(/"legacy_reports"."email" IN \('#{@employee.id}'\)/) do @employee.group.reports(true) end diff --git a/test/grouped_scope/self_grouping_test.rb b/test/grouped_scope/self_grouping_test.rb index b55539e..8155c66 100644 --- a/test/grouped_scope/self_grouping_test.rb +++ b/test/grouped_scope/self_grouping_test.rb @@ -34,6 +34,21 @@ class GroupedScope::SelfGrouppingTest < GroupedScope::TestCase end end + it 'allows you to ask if the group is present' do + @employee.update_attribute :group_id, 28 + assert_no_queries do + assert @employee.group_id.present? + assert @employee.group.present? + end + end + + it 'allows you to ask if the group is blank' do + assert_no_queries do + assert @employee.group_id.blank? + assert @employee.group.blank? + end + end + describe 'for #with_reflection' do before { @reflection = Employee.reflections[:reports] }