refactoring query.joins

This commit is contained in:
Ryan Bates
2010-07-20 17:05:17 -07:00
parent e098ddaacd
commit ba8cb3cf6d
5 changed files with 58 additions and 53 deletions

View File

@@ -3,9 +3,7 @@ module CanCan
# it holds the information about a "can" call made on Ability and provides
# helpful methods to determine permission checking and conditions hash generation.
class CanDefinition # :nodoc:
attr_reader :conditions, :block, :base_behavior
attr_reader :block
attr_reader :actions
attr_reader :base_behavior, :actions
attr_writer :expanded_actions
# The first argument when initializing is the base_behavior which is a true/false
@@ -55,20 +53,12 @@ module CanCan
@conditions == {} || @conditions.nil?
end
def association_joins(conditions = @conditions)
return nil unless conditions.kind_of?(Hash)
joins = []
conditions.each do |name, value|
if value.kind_of? Hash
nested = association_joins(value)
if nested
joins << {name => nested}
else
joins << {name => []}
end
end
def associations_hash(conditions = @conditions)
hash = {}
conditions.map do |name, value|
hash[name] = associations_hash(value) if value.kind_of? Hash
end
joins unless joins.empty?
hash
end
private

View File

@@ -32,9 +32,11 @@ module CanCan
# Returns the associations used in conditions for the :joins option of a search
# See ActiveRecordAdditions#accessible_by for use in Active Record.
def joins
unless @can_definitions.empty?
collect_association_joins(@can_definitions)
joins_hash = {}
@can_definitions.each do |can_definition|
merge_joins(joins_hash, can_definition.associations_hash)
end
clean_joins(joins_hash) unless joins_hash.empty?
end
private
@@ -67,31 +69,22 @@ module CanCan
@sanitizer.sanitize_sql(conditions)
end
def collect_association_joins(can_definitions)
joins = []
@can_definitions.each do |can_definition|
merge_association_joins(joins, can_definition.association_joins || [])
end
joins = clear_association_joins(joins)
joins unless joins.empty?
end
def merge_association_joins(what, with)
with.each do |join|
name, nested = join.each_pair.first
if at = what.detect{|h| h.has_key?(name) }
at[name] = merge_association_joins(at[name], nested)
def merge_joins(base, add)
add.each do |name, nested|
if base[name].is_a?(Hash) && !nested.empty?
merge_joins(base[name], nested)
else
what << join
base[name] = nested
end
end
end
def clear_association_joins(joins)
joins.map do |join|
name, nested = join.each_pair.first
nested.empty? ? name : {name => clear_association_joins(nested)}
def clean_joins(joins_hash)
joins = []
joins_hash.each do |name, nested|
joins << (nested.empty? ? name : {name => clean_joins(nested)})
end
joins
end
end
end