picky 4.12.8 → 4.12.10

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.
@@ -19,7 +19,7 @@ module Picky
19
19
  @@append_index = 0
20
20
  def << value
21
21
  super
22
- zadd value, @@append_index+=1
22
+ zadd value, @@append_index += 1
23
23
  end
24
24
 
25
25
  # THINK Current implementation is very brittle.
@@ -38,16 +38,14 @@ module Picky
38
38
  def dump hash
39
39
  unless @realtime
40
40
  clear
41
- # client.pipelined do
42
- hash.each_pair do |key, values|
43
- redis_key = "#{namespace}:#{key}"
44
- i = 0
45
- values.each do |value|
46
- i += 1
47
- client.zadd redis_key, i, value
48
- end
41
+ hash.each_pair do |key, values|
42
+ redis_key = "#{namespace}:#{key}"
43
+ i = 0
44
+ values.each do |value|
45
+ i += 1
46
+ client.zadd redis_key, i, value
49
47
  end
50
- # end
48
+ end
51
49
  end
52
50
  end
53
51
 
@@ -57,7 +55,9 @@ module Picky
57
55
  #
58
56
  def [] key
59
57
  list = client.zrange "#{namespace}:#{key}", :'0', :'-1'
58
+
60
59
  DirectlyManipulable.make self, list, key
60
+
61
61
  list
62
62
  end
63
63
 
@@ -72,8 +72,9 @@ module Picky
72
72
  i += 1
73
73
  client.zadd redis_key, i, value
74
74
  end
75
-
75
+
76
76
  DirectlyManipulable.make self, values, key
77
+
77
78
  values
78
79
  end
79
80
 
@@ -61,7 +61,7 @@ module Picky
61
61
  # [id] # => [:sym1, :sym2]
62
62
  #
63
63
  def create_realtime bundle
64
- List.new client, "#{bundle.identifier}:realtime", realtime: realtime
64
+ List.new client, "#{PICKY_ENVIRONMENT}:#{bundle.identifier}:realtime", realtime: realtime
65
65
  end
66
66
 
67
67
  # Does the Redis version already include
@@ -137,7 +137,7 @@ module Picky
137
137
  # else
138
138
  # class << self
139
139
  # def weight combinations
140
- combinations.score
140
+ combinations.score
141
141
  # end
142
142
  # end
143
143
  # end
@@ -217,7 +217,7 @@ module Picky
217
217
  module Scripting
218
218
  def ids combinations, amount, offset
219
219
  identifiers = combinations.inject([]) do |identifiers, combination|
220
- identifiers << "#{combination.identifier}"
220
+ identifiers << "#{PICKY_ENVIRONMENT}:#{combination.identifier}"
221
221
  end
222
222
 
223
223
  # Assume it's using EVALSHA.
@@ -18,11 +18,11 @@ module Picky
18
18
 
19
19
  lazily_initialize_client
20
20
 
21
- # Note: If on OSX, too many files get opened during
22
- # the specs -> ulimit -n 3000
23
- #
24
- # rescue SQLite3::CantOpenException => e
25
- #
21
+ # Note: If on OSX, too many files get opened during
22
+ # the specs -> ulimit -n 3000
23
+ #
24
+ # rescue SQLite3::CantOpenException => e
25
+ #
26
26
  end
27
27
 
28
28
  def initial
@@ -45,9 +45,11 @@ module Picky
45
45
  def clear
46
46
  db.execute 'delete from key_value'
47
47
  end
48
-
48
+
49
+ # TODO Replace with db method?
50
+ #
49
51
  def lazily_initialize_client
50
- @db ||= SQLite3::Database.new cache_path
52
+ @db ||= (create_directory cache_path; SQLite3::Database.new cache_path)
51
53
  end
52
54
 
53
55
  def dump_sqlite internal
@@ -65,6 +67,8 @@ module Picky
65
67
  end
66
68
 
67
69
  def reset
70
+ # TODO Still necessary?
71
+ #
68
72
  create_directory cache_path
69
73
  lazily_initialize_client
70
74
 
data/lib/picky/bundle.rb CHANGED
@@ -79,6 +79,8 @@ module Picky
79
79
 
80
80
  # Extract specific indexes from backend.
81
81
  #
82
+ # TODO Move @backend_ into the backend?
83
+ #
82
84
  def create_backends
83
85
  @backend_inverted = backend.create_inverted self
84
86
  @backend_weights = backend.create_weights self
@@ -144,6 +146,8 @@ module Picky
144
146
 
145
147
  # If a key format is set, use it, else forward to the category.
146
148
  #
149
+ # TODO What about setting the key_format per category?
150
+ #
147
151
  def key_format
148
152
  @key_format || @category.key_format
149
153
  end
@@ -1,7 +1,12 @@
1
1
  module Picky
2
2
 
3
3
  class Bundle
4
-
4
+
5
+ # TODO Push methods back into the backend, so that we
6
+ # can apply more efficient methods tailored for
7
+ # each specific backends.
8
+ #
9
+
5
10
  # Removes the given id from the indexes.
6
11
  #
7
12
  def remove id
@@ -28,6 +33,9 @@ module Picky
28
33
  @similarity.delete self.similarity_strategy.encode(str_or_sym)
29
34
  else
30
35
  @weights[str_or_sym] = self.weight_strategy.weight_for ids.size
36
+ # @weights[str_or_sym] = self.weight_strategy.respond_to?(:[]) &&
37
+ # self.weight_strategy[str_or_sym] ||
38
+ # self.weight_strategy.weight_for(ids.size)
31
39
  end
32
40
  end
33
41
 
@@ -37,6 +45,8 @@ module Picky
37
45
  # Returns a reference to the array where the id has been added.
38
46
  #
39
47
  def add id, str_or_sym, where = :unshift
48
+ # Use a generalized strategy.
49
+ #
40
50
  str_or_syms = @realtime[id] ||= []
41
51
 
42
52
  # Inverted.
@@ -49,7 +59,6 @@ module Picky
49
59
  # Update the realtime index.
50
60
  #
51
61
  str_or_syms << str_or_sym
52
-
53
62
  ids = @inverted[str_or_sym] ||= []
54
63
  ids.send where, id
55
64
  end
@@ -473,5 +473,229 @@ describe "Realtime Indexing" do
473
473
  end
474
474
  end
475
475
  end
476
+
477
+ context 'special index' do
478
+ let(:index) do
479
+ Picky::Index.new(:books) do
480
+ backend Picky::Backends::Redis.new(realtime: true)
481
+ key_format :to_s # TODO Make key format dependent on backend?
482
+ category :title
483
+ category :author, similarity: Picky::Generators::Similarity::DoubleMetaphone.new(3)
484
+ end
485
+ end
486
+ let(:books) { Picky::Search.new index }
487
+
488
+ before(:each) do
489
+ index.add Book.new('one', 'Title', 'Author')
490
+ end
491
+
492
+ context 'single category updating' do
493
+ it 'finds the first entry' do
494
+ books.search('title:Titl').ids.should == ['one']
495
+ end
496
+
497
+ it 'allows removing a single category and leaving the others alone' do
498
+ index[:title].remove 'one'
499
+
500
+ books.search('Title').ids.should == []
501
+ books.search('Author').ids.should == ['one']
502
+ end
503
+
504
+ it 'allows adding a single category and leaving the others alone' do
505
+ index[:title].add Book.new('two', 'Newtitle', 'Newauthor')
506
+
507
+ books.search('Title').ids.should == ['one']
508
+ books.search('Newtitle').ids.should == ['two']
509
+
510
+ books.search('Author').ids.should == ['one']
511
+ books.search('Newauthor').ids.should == []
512
+ end
513
+
514
+ it 'allows replacing a single category and leaving the others alone' do
515
+ index[:title].replace Book.new('one', 'Replaced', 'Notindexed')
516
+
517
+ books.search('Title').ids.should == []
518
+ books.search('Replaced').ids.should == ['one']
519
+
520
+ books.search('Notindexed').ids.should == []
521
+ books.search('Author').ids.should == ['one']
522
+ end
523
+ end
524
+
525
+ context 'with partial' do
526
+ it 'finds the first entry' do
527
+ books.search('Titl').ids.should == ['one']
528
+ end
529
+
530
+ it 'allows removing something' do
531
+ index.remove "one"
532
+ end
533
+ it 'is not findable anymore after removing' do
534
+ books.search('Titl').ids.should == ['one']
535
+
536
+ index.remove "one"
537
+
538
+ books.search('Titl').ids.should == []
539
+ end
540
+
541
+ it 'allows adding something' do
542
+ index.add Book.new('two', 'Title2', 'Author2')
543
+ end
544
+ it 'is findable after adding' do
545
+ books.search('Titl').ids.should == ['one']
546
+
547
+ index.add Book.new('two', 'Title New', 'Author New')
548
+
549
+ books.search('Titl').ids.should == ['two', 'one']
550
+ end
551
+
552
+ it 'allows replacing something' do
553
+ index.replace Book.new('one', 'Title New', 'Author New')
554
+ end
555
+ it 'is findable after replacing' do
556
+ books.search('Ne').ids.should == []
557
+
558
+ index.replace Book.new('one', 'Title New', 'Author New')
559
+
560
+ books.search('Ne').ids.should == ['one', 'one']
561
+ end
562
+ it 'handles more complex cases' do
563
+ books.search('Ne').ids.should == []
564
+
565
+ index.replace Book.new('one', 'Title New', 'Author New')
566
+
567
+ books.search('title:Ne').ids.should == ['one']
568
+ end
569
+ it 'handles more complex cases' do
570
+ index.remove "one"
571
+
572
+ books.search('Titl').ids.should == []
573
+
574
+ index.replace Book.new('one', 'Title New', 'Author New')
575
+
576
+ books.search('title:Ne').ids.should == ['one']
577
+ end
578
+ end
579
+
580
+ context 'non-partial' do
581
+ it 'finds the first entry' do
582
+ books.search('Titl').ids.should == ['one']
583
+ end
584
+
585
+ it 'allows removing something' do
586
+ index.remove "one"
587
+ end
588
+ it 'is not findable anymore after removing' do
589
+ books.search('Titl').ids.should == ['one']
590
+
591
+ index.remove :one
592
+
593
+ books.search('Titl').ids.should == []
594
+ end
595
+
596
+ it 'allows adding something' do
597
+ index.add Book.new("two", "Title2", "Author2")
598
+ end
599
+ it 'is findable after adding' do
600
+ books.search('Titl').ids.should == ['one']
601
+
602
+ index.add Book.new("two", "Title New", "Author New")
603
+
604
+ books.search('Titl').ids.should == ['two', 'one']
605
+ end
606
+
607
+ it 'allows replacing something' do
608
+ index.replace Book.new("one", "Title New", "Author New")
609
+ end
610
+ it 'is findable after replacing' do
611
+ books.search('Ne').ids.should == []
612
+
613
+ index.replace Book.new("one", "Title New", "Author New")
614
+
615
+ books.search('Ne').ids.should == ['one', 'one']
616
+ end
617
+ it 'handles more complex cases' do
618
+ books.search('Ne').ids.should == []
619
+
620
+ index.replace Book.new("one", "Title New", "Author New")
621
+
622
+ books.search('title:Ne').ids.should == ['one']
623
+ end
624
+ it 'handles more complex cases' do
625
+ index.remove "one"
626
+
627
+ books.search('Titl').ids.should == []
628
+
629
+ index.replace Book.new("one", "Title New", "Author New")
630
+
631
+ books.search('title:Ne').ids.should == ['one']
632
+ end
633
+ end
634
+
635
+ context 'similarity' do
636
+ it 'finds the first entry' do
637
+ books.search('Authr~').ids.should == ['one']
638
+ end
639
+
640
+ it 'allows removing something' do
641
+ index.remove "one"
642
+ end
643
+ it 'is not findable anymore after removing' do
644
+ books.search('Authr~').ids.should == ['one']
645
+
646
+ index.remove "one"
647
+
648
+ books.search('Authr~').ids.should == []
649
+ end
650
+
651
+ it 'allows adding something' do
652
+ index.add Book.new("two", "Title2", "Author2")
653
+ end
654
+ it 'is findable after adding' do
655
+ books.search('Authr~').ids.should == ['one']
656
+
657
+ index.add Book.new("two", "Title New", "Author New")
658
+
659
+ books.search('Authr~').ids.should == ['two', 'one']
660
+ end
661
+
662
+ it 'allows replacing something' do
663
+ index.replace Book.new("one", "Title New", "Author New")
664
+ end
665
+ it 'is findable after replacing' do
666
+ books.search('Nuw~').ids.should == []
667
+
668
+ index.replace Book.new("one", "Title New", "Author New")
669
+
670
+ books.search('Nuw~').ids.should == ['one']
671
+ end
672
+ it 'handles more complex cases' do
673
+ books.search('Now~').ids.should == []
674
+
675
+ index.replace Book.new("one", "Title New", "Author New")
676
+
677
+ books.search('author:Now~').ids.should == ['one']
678
+ end
679
+ it 'handles more complex cases' do
680
+ index.remove "one"
681
+
682
+ books.search('Athr~').ids.should == []
683
+
684
+ index.replace Book.new("one", "Title New", "Author New")
685
+
686
+ books.search('author:Athr~').ids.should == ['one']
687
+ end
688
+ it 'handles more complex cases' do
689
+ books.search('Athr~').ids.should == ['one']
690
+
691
+ index.replace Book.new("two", "Title New", "Author New")
692
+ index.add Book.new("three", "TTL", "AUTHR")
693
+
694
+ # Note: Allocations are [:two, :one], then [:three].
695
+ #
696
+ books.search('author:Athr~').ids.should == ['two', 'one', 'three']
697
+ end
698
+ end
699
+ end
476
700
 
477
701
  end
@@ -5,7 +5,7 @@ require 'sqlite3'
5
5
  describe Picky::Backends::SQLite::Array do
6
6
 
7
7
  context 'hash-based indexes' do
8
- let(:db) { described_class.new 'spec/temp/some/cache/path/to/file' }
8
+ let(:db) { described_class.new 'spec/temp/some/other/cache/path/to/file' }
9
9
 
10
10
  describe 'dump' do
11
11
  it 'forwards to the given hash' do
@@ -67,13 +67,13 @@ describe Picky::Backends::SQLite::Array do
67
67
 
68
68
  describe 'to_s' do
69
69
  it 'returns the cache path with the default file extension' do
70
- db.to_s.should == 'Picky::Backends::SQLite::Array(spec/temp/some/cache/path/to/file.sqlite3)'
70
+ db.to_s.should == 'Picky::Backends::SQLite::Array(spec/temp/some/other/cache/path/to/file.sqlite3)'
71
71
  end
72
72
  end
73
73
  end
74
74
 
75
75
  context 'hash-based indexes' do
76
- let(:db) { described_class.new 'spec/temp/some/cache/path/to/file', realtime: true }
76
+ let(:db) { described_class.new 'spec/temp/some/other/cache/path/to/file', realtime: true }
77
77
 
78
78
  describe 'dump' do
79
79
  it 'forwards to the given hash' do
@@ -135,7 +135,7 @@ describe Picky::Backends::SQLite::Array do
135
135
 
136
136
  describe 'to_s' do
137
137
  it 'returns the cache path with the default file extension' do
138
- db.to_s.should == 'Picky::Backends::SQLite::Array(spec/temp/some/cache/path/to/file.sqlite3)'
138
+ db.to_s.should == 'Picky::Backends::SQLite::Array(spec/temp/some/other/cache/path/to/file.sqlite3)'
139
139
  end
140
140
  end
141
141
  end
@@ -5,7 +5,7 @@ require 'sqlite3'
5
5
  describe Picky::Backends::SQLite::Value do
6
6
 
7
7
  context 'hash-based indexes' do
8
- let(:db) { described_class.new 'spec/temp/some/cache/path/to/file' }
8
+ let(:db) { described_class.new 'spec/temp/some/other/cache/path/to/file' }
9
9
 
10
10
  describe 'dump' do
11
11
  it 'forwards to the given hash' do
@@ -67,7 +67,7 @@ describe Picky::Backends::SQLite::Value do
67
67
 
68
68
  describe 'to_s' do
69
69
  it 'returns the cache path with the default file extension' do
70
- db.to_s.should == 'Picky::Backends::SQLite::Value(spec/temp/some/cache/path/to/file.sqlite3)'
70
+ db.to_s.should == 'Picky::Backends::SQLite::Value(spec/temp/some/other/cache/path/to/file.sqlite3)'
71
71
  end
72
72
  end
73
73
  end
@@ -102,6 +102,9 @@ describe Picky::Bundle do
102
102
  end
103
103
 
104
104
  describe 'load' do
105
+ before(:each) do
106
+ @bundle.dump # Create an index first.
107
+ end
105
108
  it 'should trigger loads' do
106
109
  @bundle.should_receive(:load_inverted).once.with
107
110
  @bundle.should_receive(:load_weights).once.with
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: 4.12.8
4
+ version: 4.12.10
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-25 00:00:00.000000000 Z
12
+ date: 2013-02-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -34,7 +34,7 @@ dependencies:
34
34
  requirements:
35
35
  - - ~>
36
36
  - !ruby/object:Gem::Version
37
- version: 4.12.8
37
+ version: 4.12.10
38
38
  type: :development
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
@@ -42,7 +42,7 @@ dependencies:
42
42
  requirements:
43
43
  - - ~>
44
44
  - !ruby/object:Gem::Version
45
- version: 4.12.8
45
+ version: 4.12.10
46
46
  - !ruby/object:Gem::Dependency
47
47
  name: text
48
48
  requirement: !ruby/object:Gem::Requirement