Browse files

Allowing for exclusive filters.

  • Loading branch information...
1 parent c35898c commit 608ab87195d1936ae87850aba12c992733a7fbaa @pat committed Nov 3, 2011
Showing with 57 additions and 9 deletions.
  1. +31 −9 lib/riddle/query/select.rb
  2. +26 −0 spec/riddle/query/select_spec.rb
View
40 lib/riddle/query/select.rb
@@ -4,6 +4,7 @@ def initialize
@indices = []
@matching = nil
@wheres = {}
+ @where_nots = {}
@group_by = nil
@order_by = nil
@order_within_group_by = nil
@@ -32,6 +33,11 @@ def where(filters = {})
self
end
+ def where_not(filters = {})
+ @where_nots.merge!(filters)
+ self
+ end
+
def group_by(attribute)
@group_by = attribute
self
@@ -79,33 +85,49 @@ def to_sql
private
def wheres?
- !(@wheres.empty? && @matching.nil?)
+ !(@wheres.empty? && @where_nots.empty? && @matching.nil?)
end
def combined_wheres
if @matching.nil?
wheres_to_s
- elsif @wheres.empty?
+ elsif @wheres.empty? && @where_nots.empty?
"MATCH('#{@matching}')"
else
"MATCH('#{@matching}') AND #{wheres_to_s}"
end
end
def wheres_to_s
- @wheres.keys.collect { |key|
- "#{key} #{filter_comparison_and_value @wheres[key]}"
- }.join(' AND ')
+ (
+ @wheres.keys.collect { |key|
+ filter_comparison_and_value key, @wheres[key]
+ } +
+ @where_nots.keys.collect { |key|
+ exclusive_filter_comparison_and_value key, @where_nots[key]
+ }
+ ).join(' AND ')
+ end
+
+ def filter_comparison_and_value(attribute, value)
+ case value
+ when Array
+ "#{attribute} IN (#{value.collect { |val| filter_value(val) }.join(', ')})"
+ when Range
+ "#{attribute} BETWEEN #{filter_value(value.first)} AND #{filter_value(value.last)}"
+ else
+ "#{attribute} = #{filter_value(value)}"
+ end
end
- def filter_comparison_and_value(value)
+ def exclusive_filter_comparison_and_value(attribute, value)
case value
when Array
- "IN (#{value.collect { |val| filter_value(val) }.join(', ')})"
+ "#{attribute} NOT IN (#{value.collect { |val| filter_value(val) }.join(', ')})"
when Range
- "BETWEEN #{filter_value(value.first)} AND #{filter_value(value.last)}"
+ "#{attribute} < #{filter_value(value.first)} OR #{attribute} > #{filter_value(value.last)}"
else
- "= #{filter_value(value)}"
+ "#{attribute} <> #{filter_value(value)}"
end
end
View
26 spec/riddle/query/select_spec.rb
@@ -32,27 +32,53 @@
should == "SELECT * FROM foo_core WHERE MATCH('foo') AND bar_id = 10"
end
+ it "handles exclusive filters with integers" do
+ query.from('foo_core').matching('foo').where_not(:bar_id => 10).to_sql.
+ should == "SELECT * FROM foo_core WHERE MATCH('foo') AND bar_id <> 10"
+ end
+
it "handles filters with true" do
query.from('foo_core').matching('foo').where(:bar => true).to_sql.
should == "SELECT * FROM foo_core WHERE MATCH('foo') AND bar = 1"
end
+ it "handles exclusive filters with true" do
+ query.from('foo_core').matching('foo').where_not(:bar => true).to_sql.
+ should == "SELECT * FROM foo_core WHERE MATCH('foo') AND bar <> 1"
+ end
+
it "handles filters with false" do
query.from('foo_core').matching('foo').where(:bar => false).to_sql.
should == "SELECT * FROM foo_core WHERE MATCH('foo') AND bar = 0"
end
+ it "handles exclusive filters with false" do
+ query.from('foo_core').matching('foo').where_not(:bar => false).to_sql.
+ should == "SELECT * FROM foo_core WHERE MATCH('foo') AND bar <> 0"
+ end
+
it "handles filters with arrays" do
query.from('foo_core').matching('foo').where(:bars => [1, 2]).to_sql.
should == "SELECT * FROM foo_core WHERE MATCH('foo') AND bars IN (1, 2)"
end
+ it "handles exclusive filters with arrays" do
+ query.from('foo_core').matching('foo').where_not(:bars => [1, 2]).to_sql.
+ should == "SELECT * FROM foo_core WHERE MATCH('foo') AND bars NOT IN (1, 2)"
+ end
+
it "handles filters with timestamps" do
time = Time.now
query.from('foo_core').matching('foo').where(:created_at => time).to_sql.
should == "SELECT * FROM foo_core WHERE MATCH('foo') AND created_at = #{time.to_i}"
end
+ it "handles exclusive filters with timestamps" do
+ time = Time.now
+ query.from('foo_core').matching('foo').where_not(:created_at => time).
+ to_sql.should == "SELECT * FROM foo_core WHERE MATCH('foo') AND created_at <> #{time.to_i}"
+ end
+
it "handles filters with ranges" do
query.from('foo_core').matching('foo').where(:bar => 1..5).to_sql.
should == "SELECT * FROM foo_core WHERE MATCH('foo') AND bar BETWEEN 1 AND 5"

0 comments on commit 608ab87

Please sign in to comment.