built a simple storage engine based on a hash and an abstract class to
have an interface for the next one
This commit is contained in:
parent
febf0a7a2e
commit
f0dbb9e39f
|
@ -8,4 +8,5 @@ module Polecat
|
|||
require 'polecat/index_searcher'
|
||||
require 'polecat/query'
|
||||
require 'polecat/term'
|
||||
require 'polecat/storage/storage'
|
||||
end
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
module Polecat
|
||||
module Storage
|
||||
# This class is a storage engine based on a simple hash.
|
||||
class HashStorage < Storage
|
||||
def initialize
|
||||
@storage = {}
|
||||
end
|
||||
|
||||
def add key, value
|
||||
check_key key
|
||||
@storage[key] = value
|
||||
end
|
||||
|
||||
def delete key
|
||||
check_key key
|
||||
@storage.delete key
|
||||
end
|
||||
|
||||
def interval lower, upper
|
||||
check_key lower
|
||||
check_key upper
|
||||
select do |key|
|
||||
lower <= key && key <= upper
|
||||
end
|
||||
end
|
||||
|
||||
def find key
|
||||
check_key key
|
||||
if @storage.has_key? key
|
||||
@storage[key]
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def select &block
|
||||
out = []
|
||||
@storage.keys.each do |key|
|
||||
out << @storage[key] if block.call(key)
|
||||
end
|
||||
out
|
||||
end
|
||||
|
||||
def count
|
||||
@storage.count
|
||||
end
|
||||
|
||||
def check_key key
|
||||
raise ArgumentError, 'key does not support #<=>' unless key.respond_to?(:<=>)
|
||||
end
|
||||
private :check_key
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,69 @@
|
|||
module Polecat
|
||||
module Storage
|
||||
# This class is a schema for building storage engines which then can be used
|
||||
# in the index.
|
||||
class Storage
|
||||
# creates a new storage
|
||||
def initialize
|
||||
end
|
||||
|
||||
# add a new value with the key
|
||||
#
|
||||
# Add a new key with a value attached to this key. The key has to
|
||||
# have an implementation of the method #<=> as it is used for comparing
|
||||
# all values.
|
||||
# @param [#<=>] key a key for searching
|
||||
# @param [Object] value the coresponding value
|
||||
def add key, value
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# delete the element with this key
|
||||
#
|
||||
# This deletes the given key. The class of key must have an implementation
|
||||
# of #<=>.
|
||||
# @param [#<=>] key the key for values to be deleted
|
||||
def delete key
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# counts the number of elements
|
||||
def count
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# returns the value for this key or nil
|
||||
#
|
||||
# Finds the key and returns the first value or nil. The key must have an
|
||||
# implementation of #<=>.
|
||||
# @param [#<=>] key the key to look for
|
||||
# @return [Object] the value of the key
|
||||
def find key
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# return all values where the block is true
|
||||
#
|
||||
# This methods evaluates the block and stores all values in an array when
|
||||
# the block evaluates to true for the given key.
|
||||
# A list with all values is returnd.
|
||||
# @yield [key] the block which gets yield with the key
|
||||
# @return [Array] all found values
|
||||
def select &block
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# search in an interval
|
||||
#
|
||||
# Search for values where the key is between the lower and the upper
|
||||
# limit. Both lower and upper must implement the method #<=>.
|
||||
# All values are returned as a list.
|
||||
# @param [#<=>] lower the lower limit
|
||||
# @param [#<=>] upper the upper limit
|
||||
# @return [Array] a list of all found values
|
||||
def interval lower, upper
|
||||
raise NotImplementedError
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,23 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
||||
require 'polecat/storage/hash_storage'
|
||||
|
||||
describe "HashStorage#add" do
|
||||
let (:s) { Polecat::Storage::HashStorage.new }
|
||||
|
||||
it "raises the element count" do
|
||||
s.add('foo', 'bar')
|
||||
s.count.should == 1
|
||||
end
|
||||
|
||||
it "raises the element count with every add" do
|
||||
s.add('foo', 1)
|
||||
s.add('bar', 2)
|
||||
s.add('baz', 3)
|
||||
s.count.should == 3
|
||||
end
|
||||
|
||||
it "raises an error when the attribute does not support #<=>" do
|
||||
s.add('foo', 'bar')
|
||||
lambda { s.add(:foo, 'baz') }.should raise_error(ArgumentError)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,27 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
||||
|
||||
describe "HashStorage#delete" do
|
||||
let (:s) { Polecat::Storage::HashStorage.new }
|
||||
before do
|
||||
s.add 'foo', 'bar'
|
||||
s.add 'bar', 'baz'
|
||||
s.add 'baz', 'foo'
|
||||
end
|
||||
|
||||
it "decrements the element count" do
|
||||
s.delete('foo')
|
||||
s.count.should == 2
|
||||
end
|
||||
|
||||
it "returns the value of the deleted key" do
|
||||
s.delete('foo').should == 'bar'
|
||||
end
|
||||
|
||||
it "returns nil when the element was not found" do
|
||||
s.delete('foobar').should be(nil)
|
||||
end
|
||||
|
||||
it "raises an error when the argument does not support #<=>" do
|
||||
lambda { s.delete(:foo) }.should raise_error(ArgumentError)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,24 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
||||
require 'polecat/storage/hash_storage'
|
||||
|
||||
describe "HashStorage#find" do
|
||||
let (:s) { Polecat::Storage::HashStorage.new }
|
||||
before do
|
||||
s.add 'foo', 'bar'
|
||||
s.add 'bar', 'baz'
|
||||
s.add 'baz', 'foobar'
|
||||
s.add 'zum', 'zum'
|
||||
end
|
||||
|
||||
it "returns nil when the element was not found" do
|
||||
s.find('baba').should be(nil)
|
||||
end
|
||||
|
||||
it "returns the value of the key" do
|
||||
s.find('foo').should == 'bar'
|
||||
end
|
||||
|
||||
it "raises an error when the type does not know #<=>" do
|
||||
lambda { s.find(:foo) }.should raise_error(ArgumentError)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,27 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
||||
|
||||
describe "HashStorage#interval" do
|
||||
let (:s) { Polecat::Storage::HashStorage.new }
|
||||
before do
|
||||
s.add 'foo', 'bar'
|
||||
s.add 'bar', 'baz'
|
||||
s.add 'baz', 'foobar'
|
||||
s.add 'zum', 'zum'
|
||||
end
|
||||
|
||||
it "returns an empty array when no element was found" do
|
||||
s.interval('a', 'b').should == []
|
||||
end
|
||||
|
||||
it "returns an array of found elements" do
|
||||
s.interval('ba', 'bb').sort.should == ['baz', 'foobar']
|
||||
end
|
||||
|
||||
it "includes the search values" do
|
||||
s.interval('bar', 'baz').sort.should == ['baz', 'foobar']
|
||||
end
|
||||
|
||||
it "raises an error when one of the arguments type does not match" do
|
||||
lambda { s.interval(1, 2) }.should raise_error(ArgumentError)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,10 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
||||
require 'polecat/storage/hash_storage'
|
||||
|
||||
describe "HashStorage#new" do
|
||||
it "creates a new storage object" do
|
||||
s = Polecat::Storage::HashStorage.new
|
||||
s.kind_of?(Polecat::Storage::Storage).should == true
|
||||
s.class.should be(Polecat::Storage::HashStorage)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,24 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
||||
|
||||
describe "HashStorage#select" do
|
||||
let (:s) { Polecat::Storage::HashStorage.new }
|
||||
before do
|
||||
s.add 'key', 'value'
|
||||
s.add 'foo', 'bar'
|
||||
s.add 'bar', 'baz'
|
||||
s.add 'baz', 'foobar'
|
||||
end
|
||||
|
||||
it "returns an empty array, when no element was selected" do
|
||||
(s.select {|element| false }).should == []
|
||||
end
|
||||
|
||||
it "takes a block as an argument" do
|
||||
(s.select {|element| element.match /ba*/ }).sort.should == ['baz', 'foobar']
|
||||
end
|
||||
|
||||
it "does not handle errors" do
|
||||
lambda { s.select {|element| raise ArgumentError }}.should(
|
||||
raise_error(ArgumentError))
|
||||
end
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
||||
|
||||
describe "Storage#add" do
|
||||
let (:s) { Polecat::Storage::Storage.new }
|
||||
|
||||
it "takes two parameters" do
|
||||
s.method(:add).arity.should == 2
|
||||
end
|
||||
|
||||
it "raises an error because it is not implemented" do
|
||||
lambda { s.add 1, 2 }.should raise_error(NotImplementedError)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
||||
|
||||
describe "Storage#count" do
|
||||
let (:s) { Polecat::Storage::Storage.new }
|
||||
|
||||
it "takes no argument" do
|
||||
s.method(:count).arity.should == 0
|
||||
end
|
||||
|
||||
it "raises an error as it is not implemented" do
|
||||
lambda { s.count }.should raise_error(NotImplementedError)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
||||
|
||||
describe "Storage#delete" do
|
||||
let (:s) { Polecat::Storage::Storage.new }
|
||||
|
||||
it "takes one argument" do
|
||||
s.method(:delete).arity.should == 1
|
||||
end
|
||||
|
||||
it "raises an error as it is not implemented" do
|
||||
lambda { s.delete 1 }.should raise_error(NotImplementedError)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
||||
|
||||
describe "Storage#find" do
|
||||
let (:s) { Polecat::Storage::Storage.new }
|
||||
|
||||
it "takes one argument" do
|
||||
s.method(:find).arity.should == 1
|
||||
end
|
||||
|
||||
it "raises an error as this method is not implemented" do
|
||||
lambda { s.find(23) }.should raise_error(NotImplementedError)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
||||
|
||||
describe "Storage#interval" do
|
||||
let (:s) { Polecat::Storage::Storage.new }
|
||||
|
||||
it "takes two arguments" do
|
||||
s.method(:interval).arity.should == 2
|
||||
end
|
||||
|
||||
it "raises an error when one of the arguments type does not match" do
|
||||
lambda { s.interval(1, 2) }.should raise_error(NotImplementedError)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,8 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
||||
|
||||
describe "Storage#new" do
|
||||
it "creates a new storage object" do
|
||||
s = Polecat::Storage::Storage.new
|
||||
s.class.should be(Polecat::Storage::Storage)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
||||
|
||||
describe "Storage#select" do
|
||||
let (:s) { Polecat::Storage::Storage.new }
|
||||
|
||||
it "takes a block as an argument" do
|
||||
s.method(:select).arity.should == 0
|
||||
end
|
||||
|
||||
it "raises an error as it is not implemented" do
|
||||
lambda { s.select }.should raise_error(NotImplementedError)
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue