lib/dusen/syntax.rb in dusen-0.5 vs lib/dusen/syntax.rb in dusen-0.5.1

- old
+ new

@@ -19,24 +19,12 @@ def search(root_scope, query) query = parse(query) if query.is_a?(String) query = query.condensed matches = find_parsed_query(root_scope, query.include) if query.exclude.any? - exclude_matches = find_parsed_query(root_scope, query.exclude) - - # extract conditions that were added by exclude tokens - sql = exclude_matches.to_sql - root_pattern = /\A#{Regexp.quote root_scope.to_sql}/ - sql =~ root_pattern or raise "Could not find ..." - sql = sql.sub(root_pattern, '') - - # negate conditions - sql = sql.sub(/^\s*WHERE\s*/i, '') - sql = sql.sub(/^\s*AND\s*/i, '') - sql = "NOT COALESCE(#{sql}, 0)" - - matches.scoped(:conditions => sql) + inverted_exclude_scope = build_exclude_scope(root_scope, query.exclude) + matches.merge(inverted_exclude_scope) else matches end end @@ -69,9 +57,27 @@ query.each do |token| scoper = @scopers[token.field] || unknown_scoper scope = scoper.call(scope, token.value) end scope + end + + def build_exclude_scope(root_scope, exclude_query) + root_scope_without_conditions = root_scope.except(:where) + exclude_scope = find_parsed_query(root_scope_without_conditions, exclude_query) + exclude_scope_conditions = exclude_scope.where_values.reduce(:and) + if exclude_scope_conditions.present? + # where_values.reduce(:and) returns a string if only one where_value given + # and a Arel::Node for more than one where_value + unless exclude_scope_conditions.is_a?(String) + exclude_scope_conditions = exclude_scope_conditions.to_sql + end + inverted_sql = "NOT COALESCE (" + exclude_scope_conditions + ",0)" + exclude_scope.except(:where).where(inverted_sql) + else + # we cannot build an inverted scope if no where-conditions are present + root_scope + end end end end