elastic_searchable 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +26 -1
- data/VERSION +1 -1
- data/elastic_searchable.gemspec +3 -3
- data/lib/elastic_searchable/active_record.rb +12 -41
- data/lib/elastic_searchable/callbacks.rb +14 -23
- data/lib/elastic_searchable/index.rb +61 -14
- data/lib/elastic_searchable.rb +5 -3
- data/test/helper.rb +3 -0
- data/test/test_elastic_searchable.rb +91 -53
- metadata +6 -6
data/README.rdoc
CHANGED
@@ -1,6 +1,31 @@
|
|
1
1
|
= elastic_searchable
|
2
2
|
|
3
|
-
|
3
|
+
Integrate the elasticsearch library into Rails.
|
4
|
+
|
5
|
+
== Usage
|
6
|
+
class Blog < ActiveRecord::Base
|
7
|
+
elastic_searchable
|
8
|
+
end
|
9
|
+
|
10
|
+
results = Blog.search 'foo'
|
11
|
+
|
12
|
+
== Features
|
13
|
+
|
14
|
+
* fast. fast! FAST! 30% faster than rubberband on average.
|
15
|
+
* active record callbacks automatically keep search index up to date as your data changes
|
16
|
+
* out of the box background indexing of data using backgrounded. Don't lock up a foreground process waiting on a background job!
|
17
|
+
* integrates with will_paginate library for easy pagination of search results
|
18
|
+
|
19
|
+
== Installation
|
20
|
+
#Gemfile
|
21
|
+
gem 'elastic_searchable'
|
22
|
+
|
23
|
+
== Configuration
|
24
|
+
|
25
|
+
#config/initializers/elastic_searchable.rb
|
26
|
+
#customize elasticsearch host
|
27
|
+
#defaults to localhost:9200
|
28
|
+
ElasticSearchable.base_uri = 'server:9200'
|
4
29
|
|
5
30
|
== Contributing to elastic_searchable
|
6
31
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0
|
data/elastic_searchable.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{elastic_searchable}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.4.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Ryan Sonnek"]
|
12
|
-
s.date = %q{2011-02-
|
12
|
+
s.date = %q{2011-02-22}
|
13
13
|
s.description = %q{integrate the elastic search engine with rails}
|
14
14
|
s.email = %q{ryan@codecrate.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -36,7 +36,7 @@ Gem::Specification.new do |s|
|
|
36
36
|
s.homepage = %q{http://github.com/wireframe/elastic_searchable}
|
37
37
|
s.licenses = ["MIT"]
|
38
38
|
s.require_paths = ["lib"]
|
39
|
-
s.rubygems_version = %q{1.5.
|
39
|
+
s.rubygems_version = %q{1.5.2}
|
40
40
|
s.summary = %q{elastic search for activerecord}
|
41
41
|
s.test_files = [
|
42
42
|
"test/helper.rb",
|
@@ -26,51 +26,22 @@ module ElasticSearchable
|
|
26
26
|
options.symbolize_keys!
|
27
27
|
self.elastic_options = options
|
28
28
|
|
29
|
-
extend ElasticSearchable::
|
29
|
+
extend ElasticSearchable::Indexing::ClassMethods
|
30
30
|
extend ElasticSearchable::Queries
|
31
31
|
|
32
|
-
include ElasticSearchable::
|
33
|
-
include ElasticSearchable::Callbacks
|
32
|
+
include ElasticSearchable::Indexing::InstanceMethods
|
33
|
+
include ElasticSearchable::Callbacks::InstanceMethods
|
34
34
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
module InstanceMethods
|
40
|
-
def indexed_json_document
|
41
|
-
self.as_json self.class.elastic_options[:json]
|
42
|
-
end
|
43
|
-
def index_in_elastic_search(lifecycle = nil)
|
44
|
-
ElasticSearchable.request :put, self.class.index_type_path(self.id), :body => self.indexed_json_document.to_json
|
45
|
-
|
46
|
-
self.run_callbacks("after_index_on_#{lifecycle}".to_sym) if lifecycle
|
47
|
-
self.run_callbacks(:after_index)
|
48
|
-
end
|
49
|
-
def should_index?
|
50
|
-
[self.class.elastic_options[:if]].flatten.compact.all? { |m| evaluate_elastic_condition(m) } &&
|
51
|
-
![self.class.elastic_options[:unless]].flatten.compact.any? { |m| evaluate_elastic_condition(m) }
|
52
|
-
end
|
53
|
-
|
54
|
-
private
|
55
|
-
#ripped from activesupport
|
56
|
-
def evaluate_elastic_condition(method)
|
57
|
-
case method
|
58
|
-
when Symbol
|
59
|
-
self.send method
|
60
|
-
when String
|
61
|
-
eval(method, self.instance_eval { binding })
|
62
|
-
when Proc, Method
|
63
|
-
method.call
|
64
|
-
else
|
65
|
-
if method.respond_to?(kind)
|
66
|
-
method.send kind
|
67
|
-
else
|
68
|
-
raise ArgumentError,
|
69
|
-
"Callbacks must be a symbol denoting the method to call, a string to be evaluated, " +
|
70
|
-
"a block to be invoked, or an object responding to the callback method."
|
71
|
-
end
|
35
|
+
backgrounded :update_index_on_create => ElasticSearchable::Callbacks.backgrounded_options, :update_index_on_update => ElasticSearchable::Callbacks.backgrounded_options
|
36
|
+
class << self
|
37
|
+
backgrounded :delete_id_from_index => ElasticSearchable::Callbacks.backgrounded_options
|
72
38
|
end
|
39
|
+
|
40
|
+
define_callbacks :after_index_on_create, :after_index_on_update, :after_index
|
41
|
+
after_commit_on_create :update_index_on_create_backgrounded, :if => :should_index?
|
42
|
+
after_commit_on_update :update_index_on_update_backgrounded, :if => :should_index?
|
43
|
+
after_commit_on_destroy :delete_from_index
|
73
44
|
end
|
74
45
|
end
|
75
46
|
end
|
76
|
-
end
|
47
|
+
end
|
@@ -1,31 +1,22 @@
|
|
1
1
|
module ElasticSearchable
|
2
2
|
module Callbacks
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
def self.backgrounded_options
|
7
|
-
{:queue => 'elasticsearch'}
|
8
|
-
end
|
9
|
-
|
10
|
-
module ClassMethods
|
11
|
-
def add_indexing_callbacks
|
12
|
-
backgrounded :update_index_on_create => ElasticSearchable::Callbacks.backgrounded_options, :update_index_on_update => ElasticSearchable::Callbacks.backgrounded_options
|
13
|
-
class << self
|
14
|
-
backgrounded :delete_id_from_index => ElasticSearchable::Callbacks.backgrounded_options
|
15
|
-
end
|
16
|
-
|
17
|
-
define_callbacks :after_index_on_create, :after_index_on_update, :after_index
|
18
|
-
after_commit_on_create :update_index_on_create_backgrounded, :if => :should_index?
|
19
|
-
after_commit_on_update :update_index_on_update_backgrounded, :if => :should_index?
|
20
|
-
after_commit_on_destroy Proc.new {|o| o.class.delete_id_from_index_backgrounded(o.id) }
|
3
|
+
class << self
|
4
|
+
def backgrounded_options
|
5
|
+
{:queue => 'elasticsearch'}
|
21
6
|
end
|
22
7
|
end
|
23
8
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
9
|
+
module InstanceMethods
|
10
|
+
private
|
11
|
+
def delete_from_index
|
12
|
+
self.class.delete_id_from_index_backgrounded self.id
|
13
|
+
end
|
14
|
+
def update_index_on_create
|
15
|
+
index_in_elastic_search :create
|
16
|
+
end
|
17
|
+
def update_index_on_update
|
18
|
+
index_in_elastic_search :update
|
19
|
+
end
|
29
20
|
end
|
30
21
|
end
|
31
22
|
end
|
@@ -1,17 +1,6 @@
|
|
1
1
|
module ElasticSearchable
|
2
|
-
module
|
3
|
-
module
|
4
|
-
|
5
|
-
# helper method to clean out existing index and reindex all objects
|
6
|
-
def rebuild_index
|
7
|
-
self.clean_index
|
8
|
-
self.update_index_mapping
|
9
|
-
self.find_each do |record|
|
10
|
-
record.index_in_elastic_search if record.should_index?
|
11
|
-
end
|
12
|
-
self.refresh_index
|
13
|
-
end
|
14
|
-
|
2
|
+
module Indexing
|
3
|
+
module ClassMethods
|
15
4
|
# delete all documents of this type in the index
|
16
5
|
# http://www.elasticsearch.com/docs/elasticsearch/rest_api/admin/indices/delete_mapping/
|
17
6
|
def clean_index
|
@@ -29,7 +18,9 @@ module ElasticSearchable
|
|
29
18
|
# create the index
|
30
19
|
# http://www.elasticsearch.com/docs/elasticsearch/rest_api/admin/indices/create_index/
|
31
20
|
def create_index
|
32
|
-
|
21
|
+
options = self.elastic_options[:index_options] ? self.elastic_options[:index_options].to_json : ''
|
22
|
+
ElasticSearchable.request :put, index_path, :body => options
|
23
|
+
self.update_index_mapping
|
33
24
|
end
|
34
25
|
|
35
26
|
# explicitly refresh the index, making all operations performed since the last refresh
|
@@ -70,5 +61,61 @@ module ElasticSearchable
|
|
70
61
|
self.elastic_options[:type] || self.table_name
|
71
62
|
end
|
72
63
|
end
|
64
|
+
|
65
|
+
module InstanceMethods
|
66
|
+
# index the object in elasticsearch
|
67
|
+
# fire after_index callbacks after operation is complete
|
68
|
+
# see http://www.elasticsearch.org/guide/reference/api/index_.html
|
69
|
+
def index_in_elastic_search(lifecycle = nil)
|
70
|
+
query = {}
|
71
|
+
query.merge! :percolate => "*" if self.class.elastic_options[:percolate]
|
72
|
+
response = ElasticSearchable.request :put, self.class.index_type_path(self.id), :query => query, :body => self.indexed_json_document.to_json
|
73
|
+
|
74
|
+
self.run_callbacks("after_index_on_#{lifecycle}".to_sym) if lifecycle
|
75
|
+
self.run_callbacks(:after_index)
|
76
|
+
|
77
|
+
if percolate_callback = self.class.elastic_options[:percolate]
|
78
|
+
matches = response['matches']
|
79
|
+
self.send percolate_callback, matches if matches.any?
|
80
|
+
end
|
81
|
+
end
|
82
|
+
# document to index in elasticsearch
|
83
|
+
def indexed_json_document
|
84
|
+
self.as_json self.class.elastic_options[:json]
|
85
|
+
end
|
86
|
+
def should_index?
|
87
|
+
[self.class.elastic_options[:if]].flatten.compact.all? { |m| evaluate_elastic_condition(m) } &&
|
88
|
+
![self.class.elastic_options[:unless]].flatten.compact.any? { |m| evaluate_elastic_condition(m) }
|
89
|
+
end
|
90
|
+
# percolate this object to see what registered searches match
|
91
|
+
# can be done on transient/non-persisted objects!
|
92
|
+
# can be done automatically when indexing using :percolate => true config option
|
93
|
+
# http://www.elasticsearch.org/blog/2011/02/08/percolator.html
|
94
|
+
def percolate
|
95
|
+
response = ElasticSearchable.request :get, self.class.index_type_path('_percolate'), :body => {:doc => self.indexed_json_document}.to_json
|
96
|
+
response['matches']
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
# ripped from activesupport
|
101
|
+
def evaluate_elastic_condition(method)
|
102
|
+
case method
|
103
|
+
when Symbol
|
104
|
+
self.send method
|
105
|
+
when String
|
106
|
+
eval(method, self.instance_eval { binding })
|
107
|
+
when Proc, Method
|
108
|
+
method.call
|
109
|
+
else
|
110
|
+
if method.respond_to?(kind)
|
111
|
+
method.send kind
|
112
|
+
else
|
113
|
+
raise ArgumentError,
|
114
|
+
"Callbacks must be a symbol denoting the method to call, a string to be evaluated, " +
|
115
|
+
"a block to be invoked, or an object responding to the callback method."
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
73
120
|
end
|
74
121
|
end
|
data/lib/elastic_searchable.rb
CHANGED
@@ -23,14 +23,16 @@ module ElasticSearchable
|
|
23
23
|
def request(method, url, options = {})
|
24
24
|
response = self.send(method, url, options)
|
25
25
|
#puts "elasticsearch request: #{method} #{url} #{" finished in #{response['took']}ms" if response['took']}"
|
26
|
-
|
26
|
+
validate_response response
|
27
27
|
response
|
28
28
|
end
|
29
29
|
|
30
30
|
private
|
31
|
-
|
31
|
+
# all elasticsearch rest calls return a json response when an error occurs. ex:
|
32
|
+
# {error: 'an error occurred' }
|
33
|
+
def validate_response(response)
|
32
34
|
error = response['error'] || "Error executing request: #{response.inspect}"
|
33
|
-
raise ElasticSearchable::ElasticError.new(error) if response['error'] || !response.response.
|
35
|
+
raise ElasticSearchable::ElasticError.new(error) if response['error'] || ![Net::HTTPOK, Net::HTTPCreated].include?(response.response.class)
|
34
36
|
end
|
35
37
|
end
|
36
38
|
end
|
data/test/helper.rb
CHANGED
@@ -20,4 +20,7 @@ ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
|
|
20
20
|
ActiveRecord::Base.establish_connection(config[ENV['DB'] || 'sqlite'])
|
21
21
|
|
22
22
|
class Test::Unit::TestCase
|
23
|
+
def delete_index
|
24
|
+
ElasticSearchable.delete '/elastic_searchable' rescue nil
|
25
|
+
end
|
23
26
|
end
|
@@ -1,24 +1,5 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'helper')
|
2
2
|
|
3
|
-
module ElasticSearch
|
4
|
-
class Client
|
5
|
-
def index_mapping(*args)
|
6
|
-
options = args.last.is_a?(Hash) ? args.pop : {}
|
7
|
-
indices = args.empty? ? [(default_index || :all)] : args.flatten
|
8
|
-
indices.collect! { |i| [:all].include?(i) ? "_#{i}" : i }
|
9
|
-
execute(:index_mapping, indices, options)
|
10
|
-
end
|
11
|
-
end
|
12
|
-
module Transport
|
13
|
-
class HTTP
|
14
|
-
def index_mapping(index_list, options={})
|
15
|
-
standard_request(:get, {:index => index_list, :op => "_mapping"})
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
|
22
3
|
class TestElasticSearchable < Test::Unit::TestCase
|
23
4
|
ActiveRecord::Schema.define(:version => 1) do
|
24
5
|
create_table :posts, :force => true do |t|
|
@@ -36,10 +17,19 @@ class TestElasticSearchable < Test::Unit::TestCase
|
|
36
17
|
t.column :name, :string
|
37
18
|
t.column :favorite_color, :string
|
38
19
|
end
|
20
|
+
create_table :books, :force => true do |t|
|
21
|
+
t.column :title, :string
|
22
|
+
end
|
39
23
|
end
|
40
24
|
|
25
|
+
def setup
|
26
|
+
delete_index
|
27
|
+
end
|
28
|
+
def teardown
|
29
|
+
delete_index
|
30
|
+
end
|
41
31
|
class Post < ActiveRecord::Base
|
42
|
-
elastic_searchable
|
32
|
+
elastic_searchable :index_options => { "analysis.analyzer.default.tokenizer" => 'standard', "analysis.analyzer.default.filter" => ["standard", "lowercase", 'porterStem'] }
|
43
33
|
after_index :indexed
|
44
34
|
after_index_on_create :indexed_on_create
|
45
35
|
def indexed
|
@@ -67,7 +57,7 @@ class TestElasticSearchable < Test::Unit::TestCase
|
|
67
57
|
end
|
68
58
|
end
|
69
59
|
|
70
|
-
context '
|
60
|
+
context 'ElasticSearchable.request with invalid url' do
|
71
61
|
should 'raise error' do
|
72
62
|
assert_raises ElasticSearchable::ElasticError do
|
73
63
|
ElasticSearchable.request :get, '/elastic_searchable/foobar/notfound'
|
@@ -75,22 +65,31 @@ class TestElasticSearchable < Test::Unit::TestCase
|
|
75
65
|
end
|
76
66
|
end
|
77
67
|
|
78
|
-
context '
|
68
|
+
context 'Post.create_index' do
|
79
69
|
setup do
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
70
|
+
Post.create_index
|
71
|
+
@status = ElasticSearchable.request :get, '/elastic_searchable/_status'
|
72
|
+
end
|
73
|
+
should 'have created index' do
|
74
|
+
assert @status['ok']
|
75
|
+
end
|
76
|
+
should 'have used custom index_options' do
|
77
|
+
expected = {
|
78
|
+
"index.number_of_replicas" => "1",
|
79
|
+
"index.number_of_shards" => "5",
|
80
|
+
"index.analysis.analyzer.default.tokenizer" => "standard",
|
81
|
+
"index.analysis.analyzer.default.filter.0" => "standard",
|
82
|
+
"index.analysis.analyzer.default.filter.1" => "lowercase",
|
83
|
+
"index.analysis.analyzer.default.filter.2" => "porterStem"
|
84
|
+
}
|
85
|
+
assert_equal expected, @status['indices']['elastic_searchable']['settings'], @status.inspect
|
85
86
|
end
|
87
|
+
end
|
86
88
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
end
|
92
|
-
should 'have created index' do
|
93
|
-
assert @status['ok']
|
89
|
+
context 'deleting object that does not exist in search index' do
|
90
|
+
should 'raise error' do
|
91
|
+
assert_raises ElasticSearchable::ElasticError do
|
92
|
+
Post.delete_id_from_index 123
|
94
93
|
end
|
95
94
|
end
|
96
95
|
end
|
@@ -109,10 +108,9 @@ class TestElasticSearchable < Test::Unit::TestCase
|
|
109
108
|
|
110
109
|
context 'with index containing multiple results' do
|
111
110
|
setup do
|
112
|
-
Post.
|
111
|
+
Post.create_index
|
113
112
|
@first_post = Post.create :title => 'foo', :body => "first bar"
|
114
113
|
@second_post = Post.create :title => 'foo', :body => "second bar"
|
115
|
-
Post.rebuild_index
|
116
114
|
Post.refresh_index
|
117
115
|
end
|
118
116
|
|
@@ -121,7 +119,7 @@ class TestElasticSearchable < Test::Unit::TestCase
|
|
121
119
|
@results = Post.search 'first'
|
122
120
|
end
|
123
121
|
should 'find created object' do
|
124
|
-
|
122
|
+
assert_contains @results, @first_post
|
125
123
|
end
|
126
124
|
should 'be paginated' do
|
127
125
|
assert_equal 1, @results.current_page
|
@@ -135,8 +133,11 @@ class TestElasticSearchable < Test::Unit::TestCase
|
|
135
133
|
setup do
|
136
134
|
@results = Post.search 'foo', :page => 2, :per_page => 1, :sort => 'id'
|
137
135
|
end
|
138
|
-
should 'find
|
139
|
-
|
136
|
+
should 'not find objects from first page' do
|
137
|
+
assert_does_not_contain @results, @first_post
|
138
|
+
end
|
139
|
+
should 'find second object' do
|
140
|
+
assert_contains @results, @second_post
|
140
141
|
end
|
141
142
|
should 'be paginated' do
|
142
143
|
assert_equal 2, @results.current_page
|
@@ -152,6 +153,7 @@ class TestElasticSearchable < Test::Unit::TestCase
|
|
152
153
|
end
|
153
154
|
should 'sort results correctly' do
|
154
155
|
assert_equal @second_post, @results.first
|
156
|
+
assert_equal @first_post, @results.last
|
155
157
|
end
|
156
158
|
end
|
157
159
|
|
@@ -174,21 +176,17 @@ class TestElasticSearchable < Test::Unit::TestCase
|
|
174
176
|
false
|
175
177
|
end
|
176
178
|
end
|
177
|
-
context 'activerecord class with :if=>proc' do
|
179
|
+
context 'activerecord class with optional :if=>proc configuration' do
|
178
180
|
context 'when creating new instance' do
|
179
181
|
setup do
|
180
182
|
Blog.any_instance.expects(:index_in_elastic_search).never
|
181
|
-
Blog.create! :title => 'foo'
|
183
|
+
@blog = Blog.create! :title => 'foo'
|
182
184
|
end
|
183
185
|
should 'not index record' do end #see expectations
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
Blog.any_instance.expects(:index_in_elastic_search).never
|
188
|
-
Blog.create! :title => 'foo'
|
189
|
-
Blog.rebuild_index
|
186
|
+
should 'not be found in elasticsearch' do
|
187
|
+
@request = ElasticSearchable.get "/elastic_searchable/blogs/#{@blog.id}"
|
188
|
+
assert @request.response.is_a?(Net::HTTPNotFound), @request.inspect
|
190
189
|
end
|
191
|
-
should 'not index record' do end #see expectations
|
192
190
|
end
|
193
191
|
end
|
194
192
|
|
@@ -198,7 +196,7 @@ class TestElasticSearchable < Test::Unit::TestCase
|
|
198
196
|
context 'activerecord class with :mapping=>{}' do
|
199
197
|
context 'creating index' do
|
200
198
|
setup do
|
201
|
-
User.
|
199
|
+
User.create_index
|
202
200
|
@status = ElasticSearchable.request :get, '/elastic_searchable/users/_mapping'
|
203
201
|
end
|
204
202
|
should 'have set mapping' do
|
@@ -217,15 +215,15 @@ class TestElasticSearchable < Test::Unit::TestCase
|
|
217
215
|
class Friend < ActiveRecord::Base
|
218
216
|
elastic_searchable :json => {:only => [:name]}
|
219
217
|
end
|
220
|
-
context 'activerecord class with :json
|
218
|
+
context 'activerecord class with optiona :json config' do
|
221
219
|
context 'creating index' do
|
222
220
|
setup do
|
223
|
-
Friend.
|
221
|
+
Friend.create_index
|
224
222
|
@friend = Friend.create! :name => 'bob', :favorite_color => 'red'
|
225
|
-
Friend.
|
223
|
+
Friend.refresh_index
|
226
224
|
end
|
227
225
|
should 'index json with configuration' do
|
228
|
-
@response = ElasticSearchable.request :get, "/
|
226
|
+
@response = ElasticSearchable.request :get, "/elastic_searchable/friends/#{@friend.id}"
|
229
227
|
expected = {
|
230
228
|
"name" => 'bob' #favorite_color should not be indexed
|
231
229
|
}
|
@@ -245,4 +243,44 @@ class TestElasticSearchable < Test::Unit::TestCase
|
|
245
243
|
assert_equal 'my_new_index', ElasticSearchable.default_index
|
246
244
|
end
|
247
245
|
end
|
246
|
+
|
247
|
+
class Book < ActiveRecord::Base
|
248
|
+
elastic_searchable :percolate => :on_percolated
|
249
|
+
def on_percolated(percolated)
|
250
|
+
@percolated = percolated
|
251
|
+
end
|
252
|
+
def percolated
|
253
|
+
@percolated
|
254
|
+
end
|
255
|
+
end
|
256
|
+
context 'Book class with percolate=true' do
|
257
|
+
context 'with created index' do
|
258
|
+
setup do
|
259
|
+
Book.create_index
|
260
|
+
end
|
261
|
+
context "when index has configured percolation" do
|
262
|
+
setup do
|
263
|
+
ElasticSearchable.request :put, '/_percolator/elastic_searchable/myfilter', :body => {:query => {:query_string => {:query => 'foo' }}}.to_json
|
264
|
+
ElasticSearchable.request :post, '/_percolator/_refresh'
|
265
|
+
end
|
266
|
+
context 'creating an object that matches the percolation' do
|
267
|
+
setup do
|
268
|
+
@book = Book.create :title => "foo"
|
269
|
+
end
|
270
|
+
should 'return percolated matches in the callback' do
|
271
|
+
assert_equal ['myfilter'], @book.percolated
|
272
|
+
end
|
273
|
+
end
|
274
|
+
context 'percolating a non-persisted object' do
|
275
|
+
setup do
|
276
|
+
@matches = Book.new(:title => 'foo').percolate
|
277
|
+
end
|
278
|
+
should 'return percolated matches' do
|
279
|
+
assert_equal ['myfilter'], @matches
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
248
285
|
end
|
286
|
+
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: elastic_searchable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 4
|
9
|
+
- 0
|
10
|
+
version: 0.4.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Ryan Sonnek
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-02-
|
18
|
+
date: 2011-02-22 00:00:00 -06:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -243,7 +243,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
243
243
|
requirements: []
|
244
244
|
|
245
245
|
rubyforge_project:
|
246
|
-
rubygems_version: 1.5.
|
246
|
+
rubygems_version: 1.5.2
|
247
247
|
signing_key:
|
248
248
|
specification_version: 3
|
249
249
|
summary: elastic search for activerecord
|