thinkingtank 0.0.5 → 0.0.6
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/lib/thinkingtank/init.rb +5 -4
- data/lib/thinkingtank/tasks.rb +3 -5
- metadata +21 -7
- data/lib/thinkingtank/indextank_client.rb +0 -255
data/lib/thinkingtank/init.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
# Require these to allow requiring thinkingtank outside a Rails app, e.g.
|
2
2
|
# for testing.
|
3
|
+
require 'rubygems'
|
4
|
+
require 'indextank'
|
5
|
+
|
3
6
|
require 'erb'
|
4
7
|
require 'yaml'
|
5
8
|
require 'singleton'
|
6
9
|
|
7
|
-
require 'thinkingtank/indextank_client'
|
8
|
-
|
9
10
|
module ThinkingTank
|
10
11
|
class Builder
|
11
12
|
def initialize(model, &block)
|
@@ -40,7 +41,7 @@ module ThinkingTank
|
|
40
41
|
conf = YAML::load(ERB.new(IO.read(path)).result)[environment]
|
41
42
|
api_url = ENV['INDEXTANK_API_URL'] || conf['api_url']
|
42
43
|
index_name = conf['index_name'] || 'default_index'
|
43
|
-
self.client = IndexTank::
|
44
|
+
self.client = IndexTank::Client.new(api_url).indexes(index_name)
|
44
45
|
end
|
45
46
|
def environment
|
46
47
|
if defined?(Merb)
|
@@ -66,7 +67,7 @@ module ThinkingTank
|
|
66
67
|
end
|
67
68
|
data[:__any] = data.values.join " . "
|
68
69
|
data[:__type] = self.class.name
|
69
|
-
it.
|
70
|
+
it.document(docid).add(data)
|
70
71
|
end
|
71
72
|
end
|
72
73
|
|
data/lib/thinkingtank/tasks.rb
CHANGED
@@ -34,14 +34,12 @@ def reindex_models
|
|
34
34
|
return false
|
35
35
|
end
|
36
36
|
|
37
|
-
if it.exists?
|
38
|
-
# Check for code because it.exists? may return true for a
|
39
|
-
# nonexistent index
|
37
|
+
if it.exists?
|
40
38
|
puts "Deleting existing index"
|
41
|
-
it.
|
39
|
+
it.delete
|
42
40
|
end
|
43
41
|
puts "Creating a new empty index"
|
44
|
-
it.
|
42
|
+
it.add
|
45
43
|
puts "Waiting for the index to be ready (this might take a while)"
|
46
44
|
while not it.running?
|
47
45
|
print "."
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: thinkingtank
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 6
|
10
|
+
version: 0.0.6
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Flaptor
|
@@ -15,10 +15,25 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-12-
|
18
|
+
date: 2010-12-24 00:00:00 -02:00
|
19
19
|
default_executable:
|
20
|
-
dependencies:
|
21
|
-
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: indextank
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 21
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
- 0
|
33
|
+
- 5
|
34
|
+
version: 0.0.5
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
22
37
|
description: |-
|
23
38
|
ActiveRecord extension that allows to define models that should be indexed in an existing IndexTank index.
|
24
39
|
It supports a very similar syntax to ThinkingSphinx allowing to easily port an existing project.
|
@@ -30,7 +45,6 @@ extensions: []
|
|
30
45
|
extra_rdoc_files: []
|
31
46
|
|
32
47
|
files:
|
33
|
-
- lib/thinkingtank/indextank_client.rb
|
34
48
|
- lib/thinkingtank/init.rb
|
35
49
|
- lib/thinkingtank/railtie.rb
|
36
50
|
- lib/thinkingtank/tasks.rb
|
@@ -1,255 +0,0 @@
|
|
1
|
-
require 'net/http'
|
2
|
-
require 'uri'
|
3
|
-
require 'rubygems'
|
4
|
-
require 'json'
|
5
|
-
|
6
|
-
module IndexTank
|
7
|
-
|
8
|
-
private
|
9
|
-
|
10
|
-
class RestClient
|
11
|
-
def GET(path, params={})
|
12
|
-
path = "#{path}?#{to_query(params)}" if params
|
13
|
-
request = Net::HTTP::Get.new "#{@uri}#{path}"
|
14
|
-
authorize request
|
15
|
-
return execute(request)
|
16
|
-
end
|
17
|
-
|
18
|
-
def PUT(path, body={})
|
19
|
-
request = Net::HTTP::Put.new "#{@uri}#{path}"
|
20
|
-
authorize request
|
21
|
-
request.body = body.to_json if body
|
22
|
-
return execute(request)
|
23
|
-
end
|
24
|
-
|
25
|
-
def DELETE(path, params={})
|
26
|
-
path = "#{path}?#{to_query(params)}" if params
|
27
|
-
request = Net::HTTP::Delete.new "#{@uri}#{path}"
|
28
|
-
authorize request
|
29
|
-
return execute(request)
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def to_query(params)
|
35
|
-
require 'cgi' unless defined?(CGI) && defined?(CGI::escape)
|
36
|
-
r = ''
|
37
|
-
params.each do |k,v|
|
38
|
-
r << "#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}&"
|
39
|
-
end
|
40
|
-
return r
|
41
|
-
end
|
42
|
-
|
43
|
-
def authorize(req)
|
44
|
-
req.basic_auth(@uri.user, @uri.password)
|
45
|
-
end
|
46
|
-
|
47
|
-
def execute(req)
|
48
|
-
res = Net::HTTP.new(@uri.host).start { |http| http.request(req) }
|
49
|
-
if res.is_a? Net::HTTPSuccess
|
50
|
-
if res.body.nil? or res.body.empty?
|
51
|
-
return res.code, nil
|
52
|
-
else
|
53
|
-
begin
|
54
|
-
return res.code, JSON.parse(res.body)
|
55
|
-
rescue
|
56
|
-
raise "Invalid JSON response: #{res.body}"
|
57
|
-
end
|
58
|
-
end
|
59
|
-
elsif res.is_a? Net::HTTPUnauthorized
|
60
|
-
raise SecurityError, "Authorization required"
|
61
|
-
elsif res.is_a? Net::HTTPBadRequest
|
62
|
-
raise ArgumentError, res.body
|
63
|
-
else
|
64
|
-
raise HttpCodeException.new(res.code, res.body)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
end
|
69
|
-
|
70
|
-
public
|
71
|
-
|
72
|
-
class ApiClient < RestClient
|
73
|
-
def initialize(api_url)
|
74
|
-
@uri = URI.parse(api_url)
|
75
|
-
end
|
76
|
-
|
77
|
-
def get_index(name)
|
78
|
-
return IndexClient.new("#{@uri}/v1/indexes/#{name}")
|
79
|
-
end
|
80
|
-
|
81
|
-
def create_index(name)
|
82
|
-
index = get_index(name)
|
83
|
-
index.create_index()
|
84
|
-
return index
|
85
|
-
end
|
86
|
-
|
87
|
-
def delete_index(name)
|
88
|
-
return get_index(name).delete_index()
|
89
|
-
end
|
90
|
-
|
91
|
-
def list_indexes()
|
92
|
-
code, indexes = GET "/v1/indexes"
|
93
|
-
return indexes.map do |name,metadata| IndexClient.new "#{@uri}/v1/indexes/#{name}", metadata end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
class IndexClient < RestClient
|
98
|
-
def initialize(index_url, metadata=nil)
|
99
|
-
@uri = URI.parse(index_url)
|
100
|
-
@metadata = metadata
|
101
|
-
end
|
102
|
-
|
103
|
-
def code
|
104
|
-
return metadata['code']
|
105
|
-
end
|
106
|
-
|
107
|
-
def running?
|
108
|
-
return metadata!['started']
|
109
|
-
end
|
110
|
-
|
111
|
-
def creation_time
|
112
|
-
return metadata['creation_time']
|
113
|
-
end
|
114
|
-
|
115
|
-
def size
|
116
|
-
return metadata['size']
|
117
|
-
end
|
118
|
-
|
119
|
-
def exists?
|
120
|
-
begin
|
121
|
-
metadata!
|
122
|
-
return true
|
123
|
-
rescue HttpCodeException
|
124
|
-
if $!.code == "404"
|
125
|
-
return false
|
126
|
-
end
|
127
|
-
raise
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
# the options argument may contain a :variables key
|
132
|
-
# with a Hash from variable numbers to their float values
|
133
|
-
# this variables can be used in the scoring functions
|
134
|
-
# when sorting a search
|
135
|
-
def add_document(docid, fields, options={})
|
136
|
-
options.merge!( :docid => docid, :fields => fields )
|
137
|
-
code, r = PUT "/docs", options
|
138
|
-
return r
|
139
|
-
end
|
140
|
-
|
141
|
-
def update_variables(docid, variables, options={})
|
142
|
-
options.merge!( :docid => docid, :variables => variables )
|
143
|
-
code, r = PUT "/docs/variables", options
|
144
|
-
return r
|
145
|
-
end
|
146
|
-
|
147
|
-
def delete_document(docid, options={})
|
148
|
-
options.merge!( :docid => docid )
|
149
|
-
code, r = DELETE "/docs", options
|
150
|
-
return r
|
151
|
-
end
|
152
|
-
|
153
|
-
# the options argument may contain an :index_code definition to override
|
154
|
-
# this instance's default index_code
|
155
|
-
def promote(docid, query, options={})
|
156
|
-
options.merge!( :docid => docid, :query => query )
|
157
|
-
code, r = PUT "/promote", options
|
158
|
-
return r
|
159
|
-
end
|
160
|
-
|
161
|
-
|
162
|
-
# the options argument may contain an :index_code definition to override
|
163
|
-
# this instance's default index_code
|
164
|
-
# it can also contain any of the following:
|
165
|
-
# :start => an int with the number of results to skip
|
166
|
-
# :len => an int with the number of results to return
|
167
|
-
# :snippet => a comma separated list of field names for which a snippet
|
168
|
-
# should be returned. (requires an index that supports snippets)
|
169
|
-
# :fetch => a comma separated list of field names for which its content
|
170
|
-
# should be returned. (requires an index that supports storage)
|
171
|
-
# :function => an int with the index of the scoring function to be used
|
172
|
-
# for this query
|
173
|
-
def search(query, options={})
|
174
|
-
options = { :start => 0, :len => 10 }.merge(options)
|
175
|
-
options.merge!( :q => query )
|
176
|
-
begin
|
177
|
-
code, r = GET "/search", options
|
178
|
-
return r
|
179
|
-
rescue HttpCodeException
|
180
|
-
raise
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
def add_function(function_index, definition, options={})
|
185
|
-
options.merge!( :definition => definition )
|
186
|
-
code, r = PUT "/functions/#{function_index}", options
|
187
|
-
return r
|
188
|
-
end
|
189
|
-
|
190
|
-
def del_function(function_index, options={})
|
191
|
-
code, r = DELETE "/functions/#{function_index}", options
|
192
|
-
return r
|
193
|
-
end
|
194
|
-
|
195
|
-
def list_functions(options={})
|
196
|
-
code, r = GET "/functions"
|
197
|
-
return r
|
198
|
-
end
|
199
|
-
|
200
|
-
def create_index()
|
201
|
-
begin
|
202
|
-
code, r = PUT ""
|
203
|
-
raise IndexAlreadyExists if code == "204"
|
204
|
-
return r
|
205
|
-
rescue HttpCodeException
|
206
|
-
if $!.code == "409"
|
207
|
-
puts $!.code
|
208
|
-
raise TooManyIndexes
|
209
|
-
end
|
210
|
-
raise
|
211
|
-
end
|
212
|
-
end
|
213
|
-
|
214
|
-
def delete_index()
|
215
|
-
code, r = DELETE ""
|
216
|
-
return r
|
217
|
-
end
|
218
|
-
|
219
|
-
def metadata
|
220
|
-
metadata! if @metadata.nil?
|
221
|
-
return @metadata
|
222
|
-
end
|
223
|
-
|
224
|
-
def metadata!
|
225
|
-
code, @metadata = GET ""
|
226
|
-
return @metadata
|
227
|
-
end
|
228
|
-
|
229
|
-
end
|
230
|
-
|
231
|
-
class IndexAlreadyExists < StandardError
|
232
|
-
end
|
233
|
-
class TooManyIndexes < StandardError
|
234
|
-
end
|
235
|
-
|
236
|
-
class HttpCodeException < StandardError
|
237
|
-
def initialize(code, message)
|
238
|
-
@code = code
|
239
|
-
@message = message
|
240
|
-
super("#{code}: #{message}")
|
241
|
-
end
|
242
|
-
|
243
|
-
attr_accessor :code
|
244
|
-
attr_accessor :message
|
245
|
-
end
|
246
|
-
|
247
|
-
class HerokuClient < ApiClient
|
248
|
-
def initialize()
|
249
|
-
super(ENV['INDEXTANK_API_URL'])
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
|
254
|
-
end
|
255
|
-
|