picky 3.1.11 → 3.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -30,16 +30,26 @@ module Picky
30
30
  @mapping_file = Memory::JSON.new "#{cache_path}.file_mapping.#{extension}"
31
31
  end
32
32
 
33
+ # The default extension for index files is "index".
34
+ #
35
+ def extension
36
+ :index
37
+ end
38
+
33
39
  # The initial content before loading.
34
40
  #
35
- def default
41
+ # Note: We could also load the mapping file
42
+ # as in #load.
43
+ #
44
+ def initial
36
45
  nil
37
46
  end
38
47
 
39
- # The default extension for index files is "index".
48
+ # The empty index that is used for putting the index
49
+ # together before it is saved into the files.
40
50
  #
41
- def extension
42
- :index
51
+ def empty
52
+ {}
43
53
  end
44
54
 
45
55
  # Will copy the index file to a location that
@@ -10,25 +10,25 @@ module Picky
10
10
  #
11
11
  class File < Backend
12
12
 
13
- # Returns an object that responds to:
13
+ # Returns an object that on #initial, #load returns an object that responds to:
14
14
  # [:token] # => [id, id, id, id, id] (an array of ids)
15
15
  #
16
16
  def create_inverted bundle
17
17
  JSON.new bundle.index_path(:inverted)
18
18
  end
19
- # Returns an object that responds to:
19
+ # Returns an object that on #initial, #load returns an object that responds to:
20
20
  # [:token] # => 1.23 (a weight)
21
21
  #
22
22
  def create_weights bundle
23
23
  JSON.new bundle.index_path(:weights)
24
24
  end
25
- # Returns an object that responds to:
25
+ # Returns an object that on #initial, #load returns an object that responds to:
26
26
  # [:encoded] # => [:original, :original] (an array of original symbols this similarity encoded thing maps to)
27
27
  #
28
28
  def create_similarity bundle
29
29
  JSON.new bundle.index_path(:similarity)
30
30
  end
31
- # Returns an object that responds to:
31
+ # Returns an object that on #initial, #load returns an object that responds to:
32
32
  # [:key] # => value (a value for this config key)
33
33
  #
34
34
  def create_configuration bundle
@@ -32,6 +32,13 @@ module Picky
32
32
  :index
33
33
  end
34
34
 
35
+ # The empty index that is used for putting the index
36
+ # together before it is dumped into the files.
37
+ #
38
+ def empty
39
+ {}
40
+ end
41
+
35
42
  # Will copy the index file to a location that
36
43
  # is in a directory named "backup" right under
37
44
  # the directory the index file is in.
@@ -16,7 +16,7 @@ module Picky
16
16
 
17
17
  # The initial content before loading.
18
18
  #
19
- def default
19
+ def initial
20
20
  {}
21
21
  end
22
22
 
@@ -16,7 +16,7 @@ module Picky
16
16
 
17
17
  # The initial content before loading.
18
18
  #
19
- def default
19
+ def initial
20
20
  {}
21
21
  end
22
22
 
@@ -18,8 +18,8 @@ module Picky
18
18
 
19
19
  # The initial content before loading.
20
20
  #
21
- def default
22
- raise "Can't have a default content from text file. Use JSON or Marshal."
21
+ def initial
22
+ raise "Can't have an initial content from text file. Use JSON or Marshal."
23
23
  end
24
24
 
25
25
  # Text files are used exclusively for
@@ -4,25 +4,25 @@ module Picky
4
4
 
5
5
  class Memory < Backend
6
6
 
7
- # Returns an object that responds to:
7
+ # Returns an object that on #initial, #load returns an object that responds to:
8
8
  # [:token] # => [id, id, id, id, id] (an array of ids)
9
9
  #
10
10
  def create_inverted bundle
11
11
  JSON.new bundle.index_path(:inverted)
12
12
  end
13
- # Returns an object that responds to:
13
+ # Returns an object that on #initial, #load returns an object that responds to:
14
14
  # [:token] # => 1.23 (a weight)
15
15
  #
16
16
  def create_weights bundle
17
17
  JSON.new bundle.index_path(:weights)
18
18
  end
19
- # Returns an object that responds to:
19
+ # Returns an object that on #initial, #load returns an object that responds to:
20
20
  # [:encoded] # => [:original, :original] (an array of original symbols this similarity encoded thing maps to)
21
21
  #
22
22
  def create_similarity bundle
23
23
  Marshal.new bundle.index_path(:similarity)
24
24
  end
25
- # Returns an object that responds to:
25
+ # Returns an object that on #initial, #load returns an object that responds to:
26
26
  # [:key] # => value (a value for this config key)
27
27
  #
28
28
  def create_configuration bundle
@@ -25,8 +25,11 @@ module Picky
25
25
 
26
26
  # The initial content before loading.
27
27
  #
28
- def default
29
- nil
28
+ # Note: As Redis indexes needn't be loaded per se,
29
+ # this just returns the same thing as #load.
30
+ #
31
+ def initial
32
+ self
30
33
  end
31
34
 
32
35
  # Returns itself.
@@ -35,6 +38,13 @@ module Picky
35
38
  self
36
39
  end
37
40
 
41
+ # The empty index that is used for putting the index
42
+ # together.
43
+ #
44
+ def empty
45
+ {}
46
+ end
47
+
38
48
  # We do not use Redis to retrieve data.
39
49
  #
40
50
  def retrieve
@@ -12,25 +12,25 @@ module Picky
12
12
  @client = options[:client] || ::Redis.new(:db => (options[:db] || 15))
13
13
  end
14
14
 
15
- # Returns an object that responds to:
15
+ # Returns an object that on #initial, #load returns an object that responds to:
16
16
  # [:token] # => [id, id, id, id, id] (an array of ids)
17
17
  #
18
18
  def create_inverted bundle
19
19
  List.new client, "#{bundle.identifier}:inverted"
20
20
  end
21
- # Returns an object that responds to:
21
+ # Returns an object that on #initial, #load returns an object that responds to:
22
22
  # [:token] # => 1.23 (a weight)
23
23
  #
24
24
  def create_weights bundle
25
25
  Float.new client, "#{bundle.identifier}:weights"
26
26
  end
27
- # Returns an object that responds to:
27
+ # Returns an object that on #initial, #load returns an object that responds to:
28
28
  # [:encoded] # => [:original, :original] (an array of original symbols this similarity encoded thing maps to)
29
29
  #
30
30
  def create_similarity bundle
31
31
  List.new client, "#{bundle.identifier}:similarity"
32
32
  end
33
- # Returns an object that responds to:
33
+ # Returns an object that on #initial, #load returns an object that responds to:
34
34
  # [:key] # => value (a value for this config key)
35
35
  #
36
36
  def create_configuration bundle
data/lib/picky/bundle.rb CHANGED
@@ -44,8 +44,9 @@ module Picky
44
44
  delegate :index_directory, :to => :category
45
45
 
46
46
  def initialize name, category, backend, weights_strategy, partial_strategy, similarity_strategy, options = {}
47
- @name = name
48
- @category = category
47
+ @name = name
48
+ @category = category
49
+
49
50
  @weights_strategy = weights_strategy
50
51
  @partial_strategy = partial_strategy
51
52
  @similarity_strategy = similarity_strategy
@@ -3,25 +3,10 @@ module Picky
3
3
  class Categories
4
4
 
5
5
  each_delegate :remove,
6
+ :add,
7
+ :replace,
6
8
  :to => :categories
7
9
 
8
- # TODO Rewrite indexing/tokenizer/caching etc.
9
- #
10
- def add object
11
- id = object.id
12
- categories.each do |category|
13
- tokens, _ = category.tokenizer.tokenize object.send(category.from).to_s
14
- category.add id, tokens
15
- end
16
- end
17
-
18
- # TODO
19
- #
20
- def replace object
21
- remove object.id
22
- add object
23
- end
24
-
25
10
  end
26
11
 
27
12
  end
@@ -1,25 +1,41 @@
1
1
  module Picky
2
2
 
3
- # TODO
4
- #
5
3
  class Category
6
4
 
7
- # TODO
5
+ # Removes an indexed object with the
6
+ # given id.
8
7
  #
9
8
  def remove id
10
9
  indexed_exact.remove id
11
10
  indexed_partial.remove id
12
11
  end
13
12
 
14
- # TODO
13
+ # Adds and indexes this category of the
14
+ # given object.
15
15
  #
16
- def add id, tokens
16
+ def add object
17
+ tokens, _ = tokenizer.tokenize object.send(from).to_s
18
+ add_tokenized object.id, tokens
19
+ end
20
+
21
+ # Removes the object's id, and then
22
+ # adds it again.
23
+ #
24
+ def replace object
25
+ remove object.id
26
+ add object
27
+ end
28
+
29
+ # For the given id, adds the list of
30
+ # strings to the index for the given id.
31
+ #
32
+ def add_tokenized id, tokens
17
33
  tokens.each do |text|
18
34
  next unless text
19
35
  text = text.to_sym
20
36
  indexed_exact.add id, text
21
37
 
22
- # TODO Refactor.
38
+ # TODO Refactor. Push into indexed_partial?
23
39
  #
24
40
  indexed_partial.partial_strategy.each_partial text do |partial_text|
25
41
  indexed_partial.add id, partial_text
@@ -23,10 +23,10 @@ module Picky
23
23
  def initialize name, category, backend, weights_strategy, partial_strategy, similarity_strategy, options = {}
24
24
  super name, category, backend, weights_strategy, partial_strategy, similarity_strategy, options
25
25
 
26
- @inverted = @backend_inverted.default
27
- @weights = @backend_weights.default
28
- @similarity = @backend_similarity.default
29
- @configuration = @backend_configuration.default
26
+ @inverted = @backend_inverted.initial
27
+ @weights = @backend_weights.initial
28
+ @similarity = @backend_similarity.initial
29
+ @configuration = @backend_configuration.initial
30
30
 
31
31
  @realtime_mapping = {} # id -> ary of syms. TODO Always instantiate?
32
32
  end
@@ -21,7 +21,9 @@ module Picky
21
21
  if ids.empty?
22
22
  @inverted.delete sym
23
23
  @weights.delete sym
24
- @similarity.delete encoded # Since no element uses this sym anymore, we can delete the similarity for it.
24
+ # Since no element uses this sym anymore, we can delete the similarity for it.
25
+ # TODO Not really. Since multiple syms can point to the same encoded.
26
+ @similarity.delete encoded
25
27
  else
26
28
  @weights[sym] = self.weights_strategy.weight_for ids.size
27
29
  end
@@ -43,10 +43,10 @@ module Picky
43
43
  @key_format = options[:key_format]
44
44
  @prepared = Backends::Memory::Text.new category.prepared_index_path
45
45
 
46
- @inverted = {}
47
- @weights = {}
48
- @similarity = {}
49
- @configuration = {}
46
+ @inverted = @backend_inverted.empty
47
+ @weights = @backend_weights.empty
48
+ @similarity = @backend_similarity.empty
49
+ @configuration = @backend_configuration.empty
50
50
  end
51
51
 
52
52
  # Sets up a piece of the index for the given token.
@@ -2,23 +2,29 @@ require 'spec_helper'
2
2
 
3
3
  describe Picky::Backends::Memory::Basic do
4
4
 
5
- let(:file) { described_class.new 'some/cache/path/to/file' }
6
-
5
+ let(:basic) { described_class.new 'some/cache/path/to/file' }
6
+
7
+ describe 'empty' do
8
+ it 'returns the container that is used for indexing' do
9
+ basic.empty.should == {}
10
+ end
11
+ end
12
+
7
13
  describe 'backup_file_path_of' do
8
14
  it 'returns a backup path relative to the path' do
9
- file.backup_file_path_of('some/path/to/some.memory.index').should == 'some/path/to/backup/some.memory.index'
15
+ basic.backup_file_path_of('some/path/to/some.memory.index').should == 'some/path/to/backup/some.memory.index'
10
16
  end
11
17
  end
12
18
 
13
19
  describe 'backup_directory' do
14
20
  it "returns the cache path's backup path" do
15
- file.backup_directory('some/cache/path/to/file').should == 'some/cache/path/to/backup'
21
+ basic.backup_directory('some/cache/path/to/file').should == 'some/cache/path/to/backup'
16
22
  end
17
23
  end
18
24
 
19
25
  describe 'to_s' do
20
26
  it 'returns the cache path with the default file extension' do
21
- file.to_s.should == 'Picky::Backends::Memory::Basic(some/cache/path/to/file.memory.index)'
27
+ basic.to_s.should == 'Picky::Backends::Memory::Basic(some/cache/path/to/file.memory.index)'
22
28
  end
23
29
  end
24
30
 
@@ -2,29 +2,43 @@ require 'spec_helper'
2
2
 
3
3
  describe Picky::Backends::Memory::JSON do
4
4
 
5
- let(:file) { described_class.new 'some/cache/path/to/file' }
6
-
7
- describe "dump" do
8
- it "delegates to the given hash" do
9
- hash = stub :hash
10
-
11
- hash.should_receive(:dump_json).once.with "some/cache/path/to/file.memory.json"
12
-
13
- file.dump hash
5
+ context 'hash-based indexes' do
6
+ let(:json) { described_class.new 'some/cache/path/to/file' }
7
+
8
+ describe 'extension' do
9
+ it 'is correct' do
10
+ json.extension.should == :json
11
+ end
14
12
  end
15
- end
16
-
17
- describe "retrieve" do
18
- it "raises" do
19
- lambda do
20
- file.retrieve
21
- end.should raise_error("Can't retrieve from JSON file. Use text file.")
13
+
14
+ describe 'initial' do
15
+ it 'is correct' do
16
+ json.initial.should == {}
17
+ end
22
18
  end
23
- end
24
-
25
- describe 'to_s' do
26
- it 'returns the cache path with the default file extension' do
27
- file.to_s.should == 'Picky::Backends::Memory::JSON(some/cache/path/to/file.memory.json)'
19
+
20
+ describe "dump" do
21
+ it "delegates to the given hash" do
22
+ hash = stub :hash
23
+
24
+ hash.should_receive(:dump_json).once.with "some/cache/path/to/file.memory.json"
25
+
26
+ json.dump hash
27
+ end
28
+ end
29
+
30
+ describe "retrieve" do
31
+ it "raises" do
32
+ lambda do
33
+ json.retrieve
34
+ end.should raise_error("Can't retrieve from JSON file. Use text file.")
35
+ end
36
+ end
37
+
38
+ describe 'to_s' do
39
+ it 'returns the cache path with the default file extension' do
40
+ json.to_s.should == 'Picky::Backends::Memory::JSON(some/cache/path/to/file.memory.json)'
41
+ end
28
42
  end
29
43
  end
30
44
 
@@ -2,29 +2,43 @@ require 'spec_helper'
2
2
 
3
3
  describe Picky::Backends::Memory::Marshal do
4
4
 
5
- let(:file) { described_class.new 'some/cache/path/to/file' }
5
+ context 'hash-based indexes' do
6
+ let(:marshal) { described_class.new 'some/cache/path/to/file' }
6
7
 
7
- describe "dump" do
8
- it "delegates to the given hash" do
9
- hash = stub :hash
8
+ describe 'extension' do
9
+ it 'is correct' do
10
+ marshal.extension.should == :dump
11
+ end
12
+ end
13
+
14
+ describe 'initial' do
15
+ it 'is correct' do
16
+ marshal.initial.should == {}
17
+ end
18
+ end
19
+
20
+ describe "dump" do
21
+ it "delegates to the given hash" do
22
+ hash = stub :hash
10
23
 
11
- hash.should_receive(:dump_marshal).once.with "some/cache/path/to/file.memory.dump"
24
+ hash.should_receive(:dump_marshal).once.with "some/cache/path/to/file.memory.dump"
12
25
 
13
- file.dump hash
26
+ marshal.dump hash
27
+ end
14
28
  end
15
- end
16
29
 
17
- describe "retrieve" do
18
- it "raises" do
19
- lambda do
20
- file.retrieve
21
- end.should raise_error("Can't retrieve from marshalled file. Use text file.")
30
+ describe "retrieve" do
31
+ it "raises" do
32
+ lambda do
33
+ marshal.retrieve
34
+ end.should raise_error("Can't retrieve from marshalled file. Use text file.")
35
+ end
22
36
  end
23
- end
24
37
 
25
- describe 'to_s' do
26
- it 'returns the cache path with the default file extension' do
27
- file.to_s.should == 'Picky::Backends::Memory::Marshal(some/cache/path/to/file.memory.dump)'
38
+ describe 'to_s' do
39
+ it 'returns the cache path with the default file extension' do
40
+ marshal.to_s.should == 'Picky::Backends::Memory::Marshal(some/cache/path/to/file.memory.dump)'
41
+ end
28
42
  end
29
43
  end
30
44
 
@@ -2,21 +2,33 @@ require 'spec_helper'
2
2
 
3
3
  describe Picky::Backends::Memory::Text do
4
4
 
5
- before(:each) do
6
- @file = described_class.new "some_cache_path"
5
+ let(:text) { described_class.new "some_cache_path" }
6
+
7
+ describe 'extension' do
8
+ it 'is correct' do
9
+ text.extension.should == :txt
10
+ end
11
+ end
12
+
13
+ describe 'initial' do
14
+ it 'raises' do
15
+ expect {
16
+ text.initial
17
+ }.to raise_error("Can't have an initial content from text file. Use JSON or Marshal.")
18
+ end
7
19
  end
8
20
 
9
21
  describe "load" do
10
22
  it "raises" do
11
23
  lambda do
12
- @file.load
24
+ text.load
13
25
  end.should raise_error("Can't load from text file. Use JSON or Marshal.")
14
26
  end
15
27
  end
16
28
  describe "dump" do
17
29
  it "raises" do
18
30
  lambda do
19
- @file.dump :anything
31
+ text.dump :anything
20
32
  end.should raise_error("Can't dump to text file. Use JSON or Marshal.")
21
33
  end
22
34
  end
@@ -27,13 +39,13 @@ describe Picky::Backends::Memory::Text do
27
39
  ::File.should_receive(:open).any_number_of_times.and_yield @io
28
40
  end
29
41
  it "yields split lines and returns the id and token text" do
30
- @file.retrieve do |id, token|
42
+ text.retrieve do |id, token|
31
43
  id.should == '123456'
32
44
  token.should == :some_nice_token
33
45
  end
34
46
  end
35
47
  it "is fast" do
36
- performance_of { @file.retrieve { |id, token| } }.should < 0.00005
48
+ performance_of { text.retrieve { |id, token| } }.should < 0.00005
37
49
  end
38
50
  end
39
51
 
@@ -16,6 +16,18 @@ describe Picky::Backends::Redis::Basic do
16
16
  end
17
17
  end
18
18
 
19
+ describe 'empty' do
20
+ it 'returns the container that is used for indexing' do
21
+ index.empty.should == {}
22
+ end
23
+ end
24
+
25
+ describe 'initial' do
26
+ it 'is correct' do
27
+ index.initial.class.should == described_class
28
+ end
29
+ end
30
+
19
31
  describe 'cache_small?' do
20
32
  context 'size 0' do
21
33
  before(:each) do
@@ -12,7 +12,7 @@ describe "Realtime Indexing" do
12
12
  end
13
13
 
14
14
  let(:index) do
15
- Picky::Index.new(:test) do
15
+ Picky::Index.new(:books) do
16
16
  source []
17
17
  category :title
18
18
  category :author, similarity: Picky::Generators::Similarity::DoubleMetaphone.new(3)
@@ -24,6 +24,39 @@ describe "Realtime Indexing" do
24
24
  index.add Book.new(1, "Title", "Author")
25
25
  end
26
26
 
27
+ context 'single category updating' do
28
+ it 'finds the first entry' do
29
+ books.search('title:Titl').ids.should == [1]
30
+ end
31
+
32
+ it 'allows removing a single category and leaving the others alone' do
33
+ index[:title].remove 1
34
+
35
+ books.search('Title').ids.should == []
36
+ books.search('Author').ids.should == [1]
37
+ end
38
+
39
+ it 'allows adding a single category and leaving the others alone' do
40
+ index[:title].add Book.new(2, "Newtitle", "Newauthor")
41
+
42
+ books.search('Title').ids.should == [1]
43
+ books.search('Newtitle').ids.should == [2]
44
+
45
+ books.search('Author').ids.should == [1]
46
+ books.search('Newauthor').ids.should == []
47
+ end
48
+
49
+ it 'allows replacing a single category and leaving the others alone' do
50
+ index[:title].replace Book.new(1, "Replaced", "Notindexed")
51
+
52
+ books.search('Title').ids.should == []
53
+ books.search('Replaced').ids.should == [1]
54
+
55
+ books.search('Notindexed').ids.should == []
56
+ books.search('Author').ids.should == [1]
57
+ end
58
+ end
59
+
27
60
  context 'with partial' do
28
61
  it 'finds the first entry' do
29
62
  books.search('Titl').ids.should == [1]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: picky
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.11
4
+ version: 3.1.12
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,12 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-10-24 00:00:00.000000000 +11:00
13
- default_executable: picky
12
+ date: 2011-10-26 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: rspec
17
- requirement: &70264818405600 !ruby/object:Gem::Requirement
16
+ requirement: &70305699965140 !ruby/object:Gem::Requirement
18
17
  none: false
19
18
  requirements:
20
19
  - - ! '>='
@@ -22,18 +21,18 @@ dependencies:
22
21
  version: '0'
23
22
  type: :development
24
23
  prerelease: false
25
- version_requirements: *70264818405600
24
+ version_requirements: *70305699965140
26
25
  - !ruby/object:Gem::Dependency
27
26
  name: picky-client
28
- requirement: &70264818404920 !ruby/object:Gem::Requirement
27
+ requirement: &70305699964660 !ruby/object:Gem::Requirement
29
28
  none: false
30
29
  requirements:
31
30
  - - =
32
31
  - !ruby/object:Gem::Version
33
- version: 3.1.11
32
+ version: 3.1.12
34
33
  type: :development
35
34
  prerelease: false
36
- version_requirements: *70264818404920
35
+ version_requirements: *70305699964660
37
36
  description: Fast Ruby semantic text search engine with comfortable single field interface.
38
37
  email: florian.hanke+picky@gmail.com
39
38
  executables:
@@ -269,7 +268,6 @@ files:
269
268
  - spec/specific/realtime_spec.rb
270
269
  - spec/specific/speed_spec.rb
271
270
  - bin/picky
272
- has_rdoc: true
273
271
  homepage: http://florianhanke.com/picky
274
272
  licenses: []
275
273
  post_install_message:
@@ -290,7 +288,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
290
288
  version: '0'
291
289
  requirements: []
292
290
  rubyforge_project: http://rubyforge.org/projects/picky
293
- rubygems_version: 1.6.2
291
+ rubygems_version: 1.8.10
294
292
  signing_key:
295
293
  specification_version: 3
296
294
  summary: ! 'Picky: Semantic Search Engine. Clever Interface. Good Tools.'