asari 0.6.0 → 0.7.0
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.
- data/README.md +33 -0
- data/lib/asari/active_record.rb +42 -5
- data/lib/asari/version.rb +1 -1
- data/spec/active_record_spec.rb +2 -2
- data/spec/conditionals_spec.rb +51 -0
- data/spec_helper.rb +53 -0
- metadata +8 -6
data/README.md
CHANGED
@@ -16,6 +16,20 @@ for easy integration with your Rails apps.
|
|
16
16
|
asari = Asari.new("my-search-domain-asdfkljwe4") # CloudSearch search domain
|
17
17
|
asari.add_item("1", { :name => "Tommy Morgan", :email => "tommy@wellbredgrapefruit.com"})
|
18
18
|
asari.search("tommy") #=> ["1"] - a list of document IDs
|
19
|
+
|
20
|
+
#### Sandbox Mode
|
21
|
+
|
22
|
+
Because there is no "local" version of CloudSearch, and search instances can be
|
23
|
+
kind of expensive, you shouldn't have to have a development version of your
|
24
|
+
index set up in order to use Asari. Because of that, Asari has a "sandbox" mode
|
25
|
+
where it does nothing with add/update/delete requests and just returns an empty
|
26
|
+
collection for any searches. This sandbox mode is enabled by default - any time
|
27
|
+
you want to actually connect to the search index, just do the following:
|
28
|
+
|
29
|
+
Asari.mode = :production
|
30
|
+
|
31
|
+
You can turn the sandbox back on, if you like, by setting the mode to `:sandbox`
|
32
|
+
again.
|
19
33
|
|
20
34
|
#### Pagination
|
21
35
|
|
@@ -64,6 +78,25 @@ with your AR objects as follows:
|
|
64
78
|
@user.asari_update_in_index
|
65
79
|
@user.asari_remove_from_index
|
66
80
|
|
81
|
+
You can also specify a :when option, like so:
|
82
|
+
|
83
|
+
asari_index("search-domain-for-users", [:name, :email, :twitter_handle,
|
84
|
+
:favorite_sweater], :when => :indexable)
|
85
|
+
|
86
|
+
or
|
87
|
+
|
88
|
+
asari_index("search-domain-for-users", [:name, :email, :twitter_handle,
|
89
|
+
:favorite_sweater], :when => Proc.new { |user| !user.admin && user.indexable })
|
90
|
+
|
91
|
+
This provides a way to mark records that shouldn't be in the index. The :when
|
92
|
+
option can be either a symbol - indicating a method on the object - or a Proc
|
93
|
+
that accepts the object as its first parameter. If the method/Proc returns true
|
94
|
+
when the object is created, the object is indexed - otherwise it is left out of
|
95
|
+
the index. If the method/Proc returns true when the object is updated, the
|
96
|
+
object is indexed - otherwise it is deleted from the index (if it has already
|
97
|
+
been added). This lets you be sure that you never have inappropriate data in
|
98
|
+
your search index.
|
99
|
+
|
67
100
|
Because index updates are done as part of the AR lifecycle by default, you also
|
68
101
|
might want to have control over how Asari handles index update errors - it's
|
69
102
|
kind of problematic, if, say, users can't sign up on your site because
|
data/lib/asari/active_record.rb
CHANGED
@@ -40,29 +40,49 @@ class Asari
|
|
40
40
|
# search_domain - the CloudSearch domain to use for indexing this model.
|
41
41
|
# fields - an array of Symbols representing the list of fields that
|
42
42
|
# should be included in this index.
|
43
|
+
# options - a hash of extra options to consider when indexing this
|
44
|
+
# model. Right now, only one option is available:
|
45
|
+
# when - a string or symbol representing a method name, or a Proc to
|
46
|
+
# evaluate to determine if this model object should be indexed. On
|
47
|
+
# creation, if the method or Proc specified returns false, the
|
48
|
+
# model will not be indexed. On update, if the method or Proc
|
49
|
+
# specified returns false, the model will be removed from the
|
50
|
+
# index (if it exists there).
|
43
51
|
#
|
44
52
|
# Examples:
|
45
53
|
# class User < ActiveRecord::Base
|
46
54
|
# include Asari::ActiveRecord
|
47
55
|
#
|
48
56
|
# asari_index("my-companies-users-asglkj4rsagkjlh34", [:name, :email])
|
57
|
+
# # or
|
58
|
+
# asari_index("my-companies-users-asglkj4rsagkjlh34", [:name, :email], :when => :should_be_indexed)
|
59
|
+
# # or
|
60
|
+
# asari_index("my-companies-users-asglkj4rsagkjlh34", [:name, :email], :when => Proc.new({ |user| user.published && !user.admin? }))
|
49
61
|
#
|
50
|
-
def asari_index(search_domain, fields)
|
51
|
-
self.class_variable_set(:@@
|
52
|
-
self.class_variable_set(:@@
|
62
|
+
def asari_index(search_domain, fields, options = {})
|
63
|
+
self.class_variable_set(:@@asari_instance, Asari.new(search_domain))
|
64
|
+
self.class_variable_set(:@@asari_fields, fields)
|
65
|
+
self.class_variable_set(:@@asari_when, options.delete(:when))
|
53
66
|
end
|
54
67
|
|
55
68
|
def asari_instance
|
56
|
-
self.class_variable_get(:@@
|
69
|
+
self.class_variable_get(:@@asari_instance)
|
57
70
|
end
|
58
71
|
|
59
72
|
def asari_fields
|
60
|
-
self.class_variable_get(:@@
|
73
|
+
self.class_variable_get(:@@asari_fields)
|
74
|
+
end
|
75
|
+
|
76
|
+
def asari_when
|
77
|
+
self.class_variable_get(:@@asari_when)
|
61
78
|
end
|
62
79
|
|
63
80
|
# Internal: method for adding a newly created item to the CloudSearch
|
64
81
|
# index. Should probably only be called from asari_add_to_index above.
|
65
82
|
def asari_add_item(obj)
|
83
|
+
if self.asari_when
|
84
|
+
return unless asari_should_index?(obj)
|
85
|
+
end
|
66
86
|
data = {}
|
67
87
|
self.asari_fields.each do |field|
|
68
88
|
data[field] = obj.send(field) || ""
|
@@ -75,6 +95,12 @@ class Asari
|
|
75
95
|
# Internal: method for updating a freshly edited item to the CloudSearch
|
76
96
|
# index. Should probably only be called from asari_update_in_index above.
|
77
97
|
def asari_update_item(obj)
|
98
|
+
if self.asari_when
|
99
|
+
unless asari_should_index?(obj)
|
100
|
+
self.asari_remove_item(obj)
|
101
|
+
return
|
102
|
+
end
|
103
|
+
end
|
78
104
|
data = {}
|
79
105
|
self.asari_fields.each do |field|
|
80
106
|
data[field] = obj.send(field)
|
@@ -92,6 +118,17 @@ class Asari
|
|
92
118
|
self.asari_on_error(e)
|
93
119
|
end
|
94
120
|
|
121
|
+
# Internal: method for looking at the when method/Proc (if defined) to
|
122
|
+
# determine whether this model should be indexed.
|
123
|
+
def asari_should_index?(object)
|
124
|
+
when_test = self.asari_when
|
125
|
+
if when_test.is_a? Proc
|
126
|
+
return Proc.call(object)
|
127
|
+
else
|
128
|
+
return object.send(when_test)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
95
132
|
# Public: method for searching the index for the specified term and
|
96
133
|
# returning all model objects that match.
|
97
134
|
#
|
data/lib/asari/version.rb
CHANGED
data/spec/active_record_spec.rb
CHANGED
@@ -5,7 +5,7 @@ describe Asari do
|
|
5
5
|
describe "when CloudSearch is responding without error" do
|
6
6
|
before :each do
|
7
7
|
@asari = double()
|
8
|
-
ActiveRecordFake.class_variable_set(:@@
|
8
|
+
ActiveRecordFake.class_variable_set(:@@asari_instance, @asari)
|
9
9
|
end
|
10
10
|
|
11
11
|
it "correctly sets up a before_destroy listener" do
|
@@ -60,7 +60,7 @@ describe Asari do
|
|
60
60
|
|
61
61
|
describe "When CloudSearch is being a problem" do
|
62
62
|
before :each do
|
63
|
-
ActiveRecordFake.class_variable_set(:@@
|
63
|
+
ActiveRecordFake.class_variable_set(:@@asari_instance, Asari.new("test-domain"))
|
64
64
|
stub_const("HTTParty", double())
|
65
65
|
HTTParty.stub(:post).and_return(fake_error_response)
|
66
66
|
HTTParty.stub(:get).and_return(fake_error_response)
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
describe Asari do
|
4
|
+
describe Asari::ActiveRecord do
|
5
|
+
describe "conditional indexing" do
|
6
|
+
describe "when a :when option is provided" do
|
7
|
+
before :each do
|
8
|
+
@arcs = ARConditionalsSpy.new
|
9
|
+
@arcs.be_indexable = false
|
10
|
+
@asari = double()
|
11
|
+
ARConditionalsSpy.class_variable_set(:@@asari_instance, @asari)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "doesn't add to the index if the :when option returns false" do
|
15
|
+
expect(@arcs.was_asked).to eq(false)
|
16
|
+
@arcs.asari_add_to_index
|
17
|
+
expect(@arcs.was_asked).to eq(true)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "doesn't add to the index if the :when option returns false" do
|
21
|
+
expect(@arcs.was_asked).to eq(false)
|
22
|
+
@arcs.asari_add_to_index
|
23
|
+
expect(@arcs.was_asked).to eq(true)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "does add to the index if the :when option returns true" do
|
27
|
+
expect(@arcs.was_asked).to eq(false)
|
28
|
+
@arcs.be_indexable = true
|
29
|
+
@asari.should_receive(:add_item).with(1, { :name => "Tommy", :email => "some@email.com"})
|
30
|
+
@arcs.asari_add_to_index
|
31
|
+
expect(@arcs.was_asked).to eq(true)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "deletes the item from the index if the :when option returns false when the item is updated" do
|
35
|
+
expect(@arcs.was_asked).to eq(false)
|
36
|
+
@asari.should_receive(:remove_item).with(1)
|
37
|
+
@arcs.asari_update_in_index
|
38
|
+
expect(@arcs.was_asked).to eq(true)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "updates the item in the index if the :when option returns true when the item is updated" do
|
42
|
+
expect(@arcs.was_asked).to eq(false)
|
43
|
+
@arcs.be_indexable = true
|
44
|
+
@asari.should_receive(:update_item).with(1, { :name => "Tommy", :email => "some@email.com"})
|
45
|
+
@arcs.asari_update_in_index
|
46
|
+
expect(@arcs.was_asked).to eq(true)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/spec_helper.rb
CHANGED
@@ -34,6 +34,7 @@ module ActiveRecord
|
|
34
34
|
end
|
35
35
|
|
36
36
|
class ActiveRecordFake
|
37
|
+
|
37
38
|
class << self
|
38
39
|
def before_destroy(sym)
|
39
40
|
@before_destroy = sym
|
@@ -78,3 +79,55 @@ class ActiveRecordFakeWithErrorOverride < ActiveRecordFake
|
|
78
79
|
false
|
79
80
|
end
|
80
81
|
end
|
82
|
+
|
83
|
+
class ARConditionalsSpy
|
84
|
+
attr_accessor :be_indexable
|
85
|
+
attr_accessor :was_asked
|
86
|
+
|
87
|
+
class << self
|
88
|
+
def before_destroy(sym)
|
89
|
+
@before_destroy = sym
|
90
|
+
end
|
91
|
+
|
92
|
+
def after_create(sym)
|
93
|
+
@after_create = sym
|
94
|
+
end
|
95
|
+
|
96
|
+
def after_update(sym)
|
97
|
+
@after_update = sym
|
98
|
+
end
|
99
|
+
|
100
|
+
def find(*args)
|
101
|
+
if args.size > 0
|
102
|
+
return [ARConditionalsSpy.new]
|
103
|
+
else
|
104
|
+
raise ActiveRecord::RecordNotFound
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
include Asari::ActiveRecord
|
110
|
+
|
111
|
+
asari_index("test-domain", [:name, :email], :when => :indexable)
|
112
|
+
|
113
|
+
def initialize
|
114
|
+
@was_asked = false
|
115
|
+
end
|
116
|
+
|
117
|
+
def id
|
118
|
+
1
|
119
|
+
end
|
120
|
+
|
121
|
+
def name
|
122
|
+
"Tommy"
|
123
|
+
end
|
124
|
+
|
125
|
+
def email
|
126
|
+
"some@email.com"
|
127
|
+
end
|
128
|
+
|
129
|
+
def indexable
|
130
|
+
@was_asked = true
|
131
|
+
@be_indexable
|
132
|
+
end
|
133
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: asari
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-07-
|
12
|
+
date: 2012-07-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: httparty
|
16
|
-
requirement: &
|
16
|
+
requirement: &70205905685040 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70205905685040
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rspec
|
27
|
-
requirement: &
|
27
|
+
requirement: &70205905684100 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70205905684100
|
36
36
|
description: Asari s a Ruby interface for AWS CloudSearch
|
37
37
|
email:
|
38
38
|
- tommy@wellbredgrapefruit.com
|
@@ -53,6 +53,7 @@ files:
|
|
53
53
|
- spec/active_record_spec.rb
|
54
54
|
- spec/asari_spec.rb
|
55
55
|
- spec/collection_spec.rb
|
56
|
+
- spec/conditionals_spec.rb
|
56
57
|
- spec/documents_spec.rb
|
57
58
|
- spec/search_spec.rb
|
58
59
|
- spec_helper.rb
|
@@ -84,6 +85,7 @@ test_files:
|
|
84
85
|
- spec/active_record_spec.rb
|
85
86
|
- spec/asari_spec.rb
|
86
87
|
- spec/collection_spec.rb
|
88
|
+
- spec/conditionals_spec.rb
|
87
89
|
- spec/documents_spec.rb
|
88
90
|
- spec/search_spec.rb
|
89
91
|
has_rdoc:
|