lib/dusen/syntax.rb in dusen-0.4.10 vs lib/dusen/syntax.rb in dusen-0.4.11

- old
+ new

@@ -15,18 +15,31 @@ def learn_unknown_field(&unknown_scoper) @unknown_scoper = unknown_scoper end def search(root_scope, query) - scope = root_scope query = parse(query) if query.is_a?(String) query = query.condensed - query.each do |token| - scoper = @scopers[token.field] || unknown_scoper - scope = scoper.call(scope, token.value) + 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) + else + matches end - scope end def fields @scopers end @@ -47,9 +60,18 @@ end end def unknown_scoper @unknown_scoper || DEFAULT_UNKNOWN_SCOPER + end + + def find_parsed_query(root_scope, query) + scope = root_scope + query.each do |token| + scoper = @scopers[token.field] || unknown_scoper + scope = scoper.call(scope, token.value) + end + scope end end end