lib/cql/map_reduce.rb in cql-1.2.1 vs lib/cql/map_reduce.rb in cql-1.3.0

- old
+ new

@@ -13,32 +13,46 @@ def self.gather_objects(current_object, target_classes, filters) gathered_objects = Array.new.tap { |gathered_objects| collect_all_in(target_classes, current_object, gathered_objects) } if filters filters.each do |filter| + negate = filter[:negate] + filter = filter[:filter] + + # Non-targeted filter, will apply to all objects if filter.is_a?(Proc) - gathered_objects = filter_with_proc(gathered_objects, filter) + gathered_objects = filter_with_proc(gathered_objects, filter, negate) + + # Targeted filter, will only apply to certain objects elsif filter.is_a?(Hash) filter.keys.each do |filtered_class| clazz = determine_class(filtered_class) gathered_objects = gathered_objects.select do |object| + + # A class that is targeted by the filter, so proceed with determination if object.is_a?(clazz) + + # Block filter if filter[filtered_class].is_a?(Proc) - filter[filtered_class].call(object) - else + filter[filtered_class].call(object) && !negate + # Must be a predefined filter otherwise - !filter_with_predefined([object], filter[filtered_class]).empty? + else + !filter_with_predefined([object], filter[filtered_class], negate).empty? end + + # Not a class that is targeted by the filter, so include it else true end end end - else + # Must be a predefined filter otherwise - gathered_objects = filter_with_predefined(gathered_objects, filter) + else + gathered_objects = filter_with_predefined(gathered_objects, filter, negate) end end end gathered_objects @@ -49,20 +63,24 @@ private - def filter_with_proc(objects, filter) - objects.select(&filter) + def filter_with_proc(objects, filter, negate) + if negate + objects.reject(&filter) + else + objects.select(&filter) + end end - def filter_with_predefined(objects, filter) - filter.execute(objects) + def filter_with_predefined(objects, filter, negate) + filter.execute(objects, negate) end # Recursively gathers all objects of the given class(es) found in the passed object (including itself). def collect_all_in(targeted_classes, current_object, accumulated_objects) - accumulated_objects << current_object if targeted_classes.any? { |targeted_class| current_object.is_a?(targeted_class) } + accumulated_objects << current_object if targeted_classes.any? { |targeted_class| (targeted_class == :all) || current_object.is_a?(targeted_class) } method_for_children = Gem.loaded_specs['cuke_modeler'].version.version[/^0/] ? :contains : :children if current_object.respond_to?(method_for_children) current_object.send(method_for_children).each do |child_object|