picky 4.12.8 → 4.12.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -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