# encoding: utf-8 # require 'spec_helper' describe 'range queries' do let(:index) do index = Picky::Index.new :range_queries do category :year category :alphabet end rangy = Struct.new :id, :year, :alphabet index.add rangy.new(1, 2000, 'g') index.add rangy.new(2, 1977, 'f') index.add rangy.new(3, 1989, 'a') index.add rangy.new(4, 2011, 'u') index.add rangy.new(5, 3000, 'v') index.add rangy.new(6, 1291, 'z') index.add rangy.new(7, 881, 'm') index.add rangy.new(8, 1984, 'l') index end let(:try) { Picky::Search.new index } it 'still works with exact queries' do try.search('1980').ids.should == [] try.search('1989').ids.should == [3] end it 'works with misses' do try.search('900-1200').ids.should == [] end it 'survives huge ranges' do try.search('0-10000 a').ids.should == [3] # Quote to make it non-partial. # try.search('0-3000"').ids.should == [7,6,2,8,3,1,4,5] end it 'is semi-reasonably fast with huge ranges' do # Quote to make it non-partial. # performance_of { try.search('0-3000"') }.should < 0.21 # Note it is much much faster with an additional token. # performance_of { try.search('0-3000 a') }.should < 0.0085 end it 'handles basic range queries' do try.search('1980-2001').ids.should == [8,3,1] try.search('f-u').ids.should == [2,1,8,7,4] end it 'can handle qualifiers' do try.search('year:1980-2001').ids.should == [8,3,1] try.search('alphabet:f-u').ids.should == [2,1,8,7,4] end it 'can be combined with other search words' do try.search('1980-2001 a').ids.should == [3] try.search('f-u 881').ids.should == [7] end it 'can handle multiple range queries' do try.search('1980-2001 a-h').ids.should == [3,1] try.search('f-u 881-1977').ids.should == [2,7] end it 'can be combined with partial queries' do try.search('198* a-h').ids.should == [3] try.search('a-h 198').ids.should == [3] end it 'works with nonsensical ranges' do try.search('h-a').ids.should == [] end # it 'handles combined range/partial queries' do # # TODO This still needs to be refined. It is madness. # # # try.search('198-200*').ids.should == [8,3,1,4,5,7,6,2] # end describe 'custom ranges' do class Wrap12Hours include Enumerable def initialize(min, max) @hours = 12 @min = min.to_i @top = max.to_i @top += @hours if @top < @min end def each @min.upto(@top).each do |i| yield (i % @hours).to_s end end end let(:index) do index = Picky::Index.new :range_queries do category :hour, ranging: Wrap12Hours, partial: Picky::Partial::None.new end rangy = Struct.new :id, :hour index.add rangy.new(1, 0) index.add rangy.new(2, 1) index.add rangy.new(3, 4) index.add rangy.new(4, 5) index.add rangy.new(5, 11) index.add rangy.new(6, 10) index.add rangy.new(7, 2) index.add rangy.new(8, 3) index end it 'allows injection of custom range classes' do try.search('hour:10-2').ids.should == [6, 5, 1, 2, 7] end it 'allows injection of custom range classes' do try.search('hour:0-11').ids.should == [1, 2, 7, 8, 3, 4, 6, 5] end end end