ripplr 0.0.4.beta → 0.0.5.beta

Sign up to get free protection for your applications and to get access to all the features.
@@ -1 +1 @@
1
- require File.join("ripplr", "errors", "key_not_specified_error")
1
+ require File.join("ripplr", "errors", "field_not_queryable_error")
@@ -0,0 +1,13 @@
1
+ require 'ripplr/translation'
2
+
3
+ class Ripplr::FieldNotQueryableError
4
+ include Ripplr::Translation
5
+
6
+ def initialize(field_name)
7
+ @field_name = field_name
8
+ end
9
+
10
+ def exception(message=t("errors.field_not_queryable", :field => @field_name))
11
+ RuntimeError.new message
12
+ end
13
+ end
@@ -4,6 +4,11 @@ module Ripplr
4
4
  def self.index(queryable_obj)
5
5
  ::Ripple.client.index queryable_obj.bucket_name, queryable_obj.indexes_as
6
6
  end
7
+
8
+ def self.search(klass, query)
9
+ results = ::Ripple.client.search(klass.bucket.name, query)["response"]["docs"]
10
+ results.map{|result| klass.find(result["id"])}.reject{|obj| obj.nil?}
11
+ end
7
12
  end
8
13
  end
9
14
  end
@@ -1,3 +1,4 @@
1
1
  en:
2
2
  ripplr:
3
- key_not_specified: "Cannot index an object that does not specify a key."
3
+ errors:
4
+ field_not_queryable: "\"%{field}\" is not a queryable field."
@@ -2,16 +2,19 @@ module Ripplr
2
2
  class QueryField
3
3
  def initialize(type, property_name)
4
4
  @type = type
5
- @property = property_name
5
+ @property_name = property_name
6
6
  end
7
7
 
8
8
  def indexes_as(queryable_object)
9
- return { index_name(@type, @property) => queryable_object.send(@property) }
9
+ return { index_name => queryable_object.send(@property_name) }
10
10
  end
11
11
 
12
- private
13
- def index_name(type, property_name)
14
- "#{property_name.to_s}_#{type.to_s}".to_sym
12
+ def for?(property_name)
13
+ @property_name == property_name
14
+ end
15
+
16
+ def index_name
17
+ "#{@property_name.to_s}_#{@type.to_s}".to_sym
15
18
  end
16
19
  end
17
20
  end
@@ -1,7 +1,7 @@
1
1
  module Ripplr
2
2
  module Queryable
3
- def index(indexer=Ripple.client)
4
- indexer.index(self)
3
+ def index(indexer=Ripplr::Indexers::Ripple)
4
+ indexer.index self
5
5
  end
6
6
 
7
7
  def remove_index(indexer=Ripple.client)
@@ -29,6 +29,10 @@ module Ripplr
29
29
  end
30
30
 
31
31
  module QueryableClassMethods
32
+ def find(property, query, indices=Ripplr::Indexers::Ripple)
33
+ indices.search self, "#{queryable_field(property)}: \"#{query}\""
34
+ end
35
+
32
36
  def query_fields
33
37
  @query_fields ||= Array.new
34
38
  @query_fields
@@ -49,6 +53,14 @@ module Ripplr
49
53
  query_fields << Ripplr::QueryField.new(:text, name)
50
54
  end
51
55
  end
56
+
57
+ protected
58
+ def queryable_field(property_name)
59
+ matches = query_fields.select{|f| f.for? property_name}
60
+ raise Ripplr::FieldNotQueryableError.new(property_name) if matches.empty?
61
+
62
+ matches.first.index_name
63
+ end
52
64
  end
53
65
  end
54
66
  end
@@ -1,3 +1,3 @@
1
1
  module Ripplr
2
- VERSION = "0.0.4.beta"
2
+ VERSION = "0.0.5.beta"
3
3
  end
@@ -8,4 +8,47 @@ describe Ripplr::Indexers::Ripple do
8
8
  Then { Ripplr::Indexers::Ripple.index(model).should be_true }
9
9
  end
10
10
 
11
+ describe "#search" do
12
+ context "when no documents match" do
13
+ Given (:results) { {"response" => {"docs" => []} } }
14
+ Given { Ripple.client.should_receive(:search).with('people', 'query string').and_return results }
15
+ When(:result) { Ripplr::Indexers::Ripple.search Person, 'query string' }
16
+ Then { result.should be_empty }
17
+ end
18
+
19
+ context "when one document matches" do
20
+ Given (:results) { {"response" => {"docs" => [ { "id" => "12345"} ]} } }
21
+ Given { Person.should_receive(:find).with("12345").and_return "yo dawg" }
22
+ Given { Ripple.client.should_receive(:search).with('people', 'query string').and_return results }
23
+ When(:result) { Ripplr::Indexers::Ripple.search Person, 'query string' }
24
+ Then { result.first.should == "yo dawg" }
25
+ end
26
+
27
+ context "when one document matches but it doesnt exist" do
28
+ Given (:results) { {"response" => {"docs" => [ { "id" => "12345"} ]} } }
29
+ Given { Person.should_receive(:find).with("12345").and_return nil }
30
+ Given { Ripple.client.should_receive(:search).with('people', 'query string').and_return results }
31
+ When(:result) { Ripplr::Indexers::Ripple.search Person, 'query string' }
32
+ Then { result.should be_empty }
33
+ end
34
+ end
11
35
  end
36
+
37
+
38
+ ## EXAMPLE SEARCH RESULT ##
39
+ ###########################
40
+ # {"responseHeader"=>
41
+ # {"status"=>0, "QTime"=>2, "params"=>{"q"=>"title_text: Skrillex", "q.op"=>"or", "filter"=>"", "wt"=>"json"}},
42
+ # {"response" =>
43
+ # {
44
+ # "numFound"=>3,
45
+ # "start"=>0,
46
+ # "maxScore"=>"0.353553",
47
+ # "docs"=>[
48
+ # { "id"=>"GDdq2m1xI2URV34HTWC1UfBRC3n",
49
+ # "index"=>"vera_access_checklists",
50
+ # "fields"=>
51
+ # {"created_at_dt"=>"2012-09-06 19:17:20 UTC",
52
+ # "title_text"=>"skrillex"},
53
+ # "props"=>{}} ]
54
+ # }
@@ -15,10 +15,34 @@ describe Ripplr::Queryable do
15
15
  Then { Person.new.bucket_name.should == "people" }
16
16
  end
17
17
 
18
- describe "#indexing" do
19
- Given (:friend) { Person.new }
20
- Given (:service) { mock :index => true }
21
- Then { friend.index(service).should be_true }
18
+ describe "#find" do
19
+ context "when using a field that has been defiend as queryable" do
20
+ Given (:indexer) { mock }
21
+ Given { indexer.should_receive(:search).with(Person,"first_name_text: \"Dan\"").and_return ["Dan Auerbach"] }
22
+ When (:result) { Person.find :first_name, "Dan", indexer }
23
+ Then { result.should == [ "Dan Auerbach" ] }
24
+ end
25
+
26
+ context "when using a field that has not been defined as queryable" do
27
+ Then { expect { Person.find :full_name, "val" }.to raise_error RuntimeError }
28
+ end
29
+
30
+ context "when the object does not have any queryable fields" do
31
+ Then { expect { Unqueryable.find :something, "what what" }.to raise_error RuntimeError }
32
+ end
33
+ end
34
+
35
+ describe "#index" do
36
+ context "overide indexer" do
37
+ Given (:friend) { Person.new }
38
+ Given (:service) { mock :index => true }
39
+ Then { friend.index(service).should be_true }
40
+ end
41
+ context "default indexer" do
42
+ Given (:rg3) { Person.new }
43
+ Given { Ripplr::Indexers::Ripple.should_receive(:index).with(rg3).and_return true }
44
+ Then { rg3.index.should be_true }
45
+ end
22
46
  end
23
47
 
24
48
  describe "#indexes_as" do
@@ -1,3 +1,9 @@
1
- require File.join("support", "models", "person")
2
- require File.join("support", "models", "lift")
3
- require File.join("support", "models", "log_entry")
1
+ %w[
2
+ person
3
+ lift
4
+ log_entry
5
+ unqueryable
6
+ ].each do |file|
7
+ require File.join("support", "models", file)
8
+ end
9
+
@@ -0,0 +1,4 @@
1
+ class Unqueryable
2
+ include Ripple::Document
3
+ include Ripplr::Queryable
4
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ripplr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4.beta
4
+ version: 0.0.5.beta
5
5
  prerelease: 6
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: 2012-09-07 00:00:00.000000000 Z
12
+ date: 2012-09-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec-given
@@ -70,7 +70,7 @@ extra_rdoc_files: []
70
70
  files:
71
71
  - Gemfile
72
72
  - Gemfile.lock
73
- - lib/ripplr/errors/key_not_specified_error.rb
73
+ - lib/ripplr/errors/field_not_queryable_error.rb
74
74
  - lib/ripplr/errors.rb
75
75
  - lib/ripplr/formatters/riak.rb
76
76
  - lib/ripplr/formatters.rb
@@ -93,6 +93,7 @@ files:
93
93
  - spec/support/models/lift.rb
94
94
  - spec/support/models/log_entry.rb
95
95
  - spec/support/models/person.rb
96
+ - spec/support/models/unqueryable.rb
96
97
  - spec/support/models.rb
97
98
  - .gitignore
98
99
  homepage: https://github.com/validas/Ripplr
@@ -128,5 +129,6 @@ test_files:
128
129
  - spec/support/models/lift.rb
129
130
  - spec/support/models/log_entry.rb
130
131
  - spec/support/models/person.rb
132
+ - spec/support/models/unqueryable.rb
131
133
  - spec/support/models.rb
132
134
  - .gitignore
@@ -1,9 +0,0 @@
1
- require 'ripplr/translation'
2
-
3
- class Ripplr::KeyNotSpecifiedError
4
- include Ripplr::Translation
5
-
6
- def exception(message=t("key_not_specified"))
7
- RuntimeError.new message
8
- end
9
- end