Skip to content

Commit

Permalink
Breaking up lib modules for class and instance methods. Also make dyn…
Browse files Browse the repository at this point in the history
…amic belongs_to :grouping check for association first.
  • Loading branch information
metaskills committed Sep 19, 2008
1 parent 813effd commit e3adcd6
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 64 deletions.
2 changes: 1 addition & 1 deletion autotest/railsplugin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ def initialize
# self.libs = %w[. lib test].join(File::PATH_SEPARATOR)

# Ignore these directories in the plugin.
add_exception %r%^\./(?:autotest|tasks|\.git)%
add_exception %r%^\./(?:autotest|tasks)%

# Ignore these ruby files in the root of the plugin folder.
add_exception %r%^\./(install|uninstall)\.rb$%
Expand Down
66 changes: 4 additions & 62 deletions lib/grouped_scope.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,74 +2,16 @@
require 'grouped_scope/proxy'
require 'grouped_scope/grouping'
require 'grouped_scope/group'
require 'grouped_scope/class_methods'
require 'grouped_scope/instance_methods'
require 'grouped_scope/has_many_association'

module GroupedScope

VERSION = '1.0.0'

def self.included(klass) #:nodoc:
klass.class_eval do
extend ClassMethods
end
end


module ClassMethods

def grouped_scopes
read_inheritable_attribute(:grouped_scopes) || write_inheritable_attribute(:grouped_scopes, {})
end

def grouped_scope(*args)
belongs_to :grouping, :foreign_key => 'group_id', :class_name => 'GroupedScope::Grouping'
args.each do |association|
ung_assoc = reflect_on_association(association)
unless ung_assoc && ung_assoc.macro == :has_many
raise ArgumentError, "Cannot create a group scope for :#{association} because it is not a has_many association."
end
group_association = "group_#{association}".to_sym
grouped_scopes[group_association] = true
group_association_options = {:class_name => ung_assoc.class_name, :foreign_key => ung_assoc.primary_key_name}
group_association_options.merge!(ung_assoc.options)
has_many group_association, group_association_options
end
include InstanceMethods
end

end

module InstanceMethods

def group
@group ||= Group.new(self)
end

end

module HasManyAssociation

def self.included(klass)
klass.class_eval do
alias_method_chain :construct_sql, :group_scope
end
end

def construct_sql_with_group_scope
if @owner.class.grouped_scopes[@reflection.name]
@finder_sql = "#{@reflection.klass.table_name}.#{@reflection.primary_key_name} IN (#{@owner.group.quoted_ids})"
@finder_sql << " AND (#{conditions})" if conditions
@counter_sql = @finder_sql
else
construct_sql_without_group_scope
end
end

end

end


ActiveRecord::Base.send :include, GroupedScope
ActiveRecord::Base.send :extend, GroupedScope::ClassMethods
ActiveRecord::Associations::HasManyAssociation.send :include, GroupedScope::HasManyAssociation


34 changes: 34 additions & 0 deletions lib/grouped_scope/class_methods.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
module GroupedScope
module ClassMethods

def grouped_scopes
read_inheritable_attribute(:grouped_scopes) || write_inheritable_attribute(:grouped_scopes, {})
end

def grouped_scope(*args)
belongs_to_grouped_scope_grouping
args.each do |association|
ung_assoc = reflect_on_association(association)
unless ung_assoc && ung_assoc.macro == :has_many
raise ArgumentError, "Cannot create a group scope for :#{association} because it is not a has_many association."
end
grouped_scopes[association] = true
group_association_options = {:class_name => ung_assoc.class_name, :foreign_key => ung_assoc.primary_key_name}
group_association_options.merge!(ung_assoc.options)
has_many "group_#{association}".to_sym, group_association_options
end
include InstanceMethods
end

private

def belongs_to_grouped_scope_grouping
grouping_class_name = 'GroupedScope::Grouping'
existing_grouping = reflect_on_association(:grouping)
return false if existing_grouping && existing_grouping.macro == :belongs_to && existing_grouping.options[:class_name] == grouping_class_name
belongs_to :grouping, :foreign_key => 'group_id', :class_name => grouping_class_name
end


end
end
2 changes: 1 addition & 1 deletion lib/grouped_scope/group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def initialize(owner)

def method_missing(method, *args, &block)
group_method = "group_#{method}".to_sym
if proxy_class.grouped_scopes[group_method]
if proxy_class.grouped_scopes[method]
proxy_owner.send(group_method, *args, &block)
else
super
Expand Down
22 changes: 22 additions & 0 deletions lib/grouped_scope/has_many_association.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module GroupedScope
module HasManyAssociation

def self.included(klass)
klass.class_eval do
alias_method_chain :construct_sql, :group_scope
end
end

def construct_sql_with_group_scope
if @owner.class.grouped_scopes[@reflection.name]
@finder_sql = "#{@reflection.klass.table_name}.#{@reflection.primary_key_name} IN (#{@owner.group.quoted_ids})"
@finder_sql << " AND (#{conditions})" if conditions
@counter_sql = @finder_sql
else
construct_sql_without_group_scope
end
end

end
end

10 changes: 10 additions & 0 deletions lib/grouped_scope/instance_methods.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module GroupedScope
module InstanceMethods

def group
@group ||= Group.new(self)
end


end
end
37 changes: 37 additions & 0 deletions test/grouped_scope/class_methods_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
require File.dirname(__FILE__) + '/../helper'

class ClassMethodsTest < Test::Unit::TestCase

def setup
setup_environment
end

context 'For .grouped_scopes' do

should 'have a inheritable attribute hash' do
assert_instance_of Hash, Employee.grouped_scopes
end

should 'add to inheritable attributes with new grouped_scope' do
assert_nil Employee.grouped_scopes[:foobars]
Employee.class_eval { has_many(:foobars) ; grouped_scope(:foobars) }
assert Employee.grouped_scopes[:foobars]
end

end

context 'For .grouped_scope' do

should 'create a belongs_to :grouping association' do
assert Employee.reflect_on_association(:grouping)
end

should 'not create more belongs_to :grouping on additional calls' do
Employee.expects(:has_many).with(:grouping).never
Employee.class_eval { has_many(:foobars) ; grouped_scope(:foobars) }
end

end


end

0 comments on commit e3adcd6

Please sign in to comment.