asari 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|