thinkingtank 0.0.4 → 0.0.5
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.rb +14 -0
- data/lib/thinkingtank/activerecord_extensions.rb +60 -0
- data/lib/{indextank_client.rb → thinkingtank/indextank_client.rb} +1 -1
- data/lib/thinkingtank/init.rb +13 -65
- data/lib/thinkingtank/railtie.rb +9 -0
- data/lib/thinkingtank/tasks.rb +34 -7
- metadata +13 -8
- data/README +0 -67
- data/rails/init.rb +0 -4
- data/tasks/rails.rake +0 -1
data/lib/thinkingtank.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rails'
|
2
|
+
require 'thinkingtank/init'
|
3
|
+
|
4
|
+
if defined?(Rails::Railtie)
|
5
|
+
# Rails 3
|
6
|
+
# The Railtie will load the Activerecord extensions at the appropriate
|
7
|
+
# point in the boot process
|
8
|
+
require 'thinkingtank/railtie'
|
9
|
+
else
|
10
|
+
# Rails 2
|
11
|
+
# Load the extensions now, since we don't have fine-grained control like
|
12
|
+
# in a Railtie
|
13
|
+
require 'thinkingtank/activerecord_extensions'
|
14
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'thinkingtank/init'
|
2
|
+
|
3
|
+
class << ActiveRecord::Base
|
4
|
+
@indexable = false
|
5
|
+
def search(*args)
|
6
|
+
return indextank_search(true, *args)
|
7
|
+
end
|
8
|
+
def search_raw(*args)
|
9
|
+
return indextank_search(false, *args)
|
10
|
+
end
|
11
|
+
|
12
|
+
def define_index(name = nil, &block)
|
13
|
+
include ThinkingTank::IndexMethods
|
14
|
+
@thinkingtank_builder = ThinkingTank::Builder.new self, &block
|
15
|
+
@indexable = true
|
16
|
+
after_save :update_index
|
17
|
+
end
|
18
|
+
|
19
|
+
def is_indexable?
|
20
|
+
return @indexable
|
21
|
+
end
|
22
|
+
|
23
|
+
def thinkingtank_builder
|
24
|
+
return @thinkingtank_builder
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def indextank_search(models, *args)
|
30
|
+
options = args.extract_options!
|
31
|
+
query = args.join(' ')
|
32
|
+
|
33
|
+
# transform fields in query
|
34
|
+
|
35
|
+
if options.has_key? :conditions
|
36
|
+
options[:conditions].each do |field,value|
|
37
|
+
query += " #{field}:(#{value})"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
options.slice!(:snippet, :fetch, :function)
|
42
|
+
|
43
|
+
it = ThinkingTank::Configuration.instance.client
|
44
|
+
models = []
|
45
|
+
res = it.search("__any:(#{query.to_s}) __type:#{self.name}", options)
|
46
|
+
if models
|
47
|
+
res['results'].each do |doc|
|
48
|
+
type, docid = doc['docid'].split(" ", 2)
|
49
|
+
models << self.find(id=docid)
|
50
|
+
end
|
51
|
+
return models
|
52
|
+
else
|
53
|
+
res['results'].each do |doc|
|
54
|
+
type, docid = doc['docid'].split(" ", 2)
|
55
|
+
doc['model'] = self.find(id=docid)
|
56
|
+
end
|
57
|
+
return res
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/thinkingtank/init.rb
CHANGED
@@ -1,4 +1,10 @@
|
|
1
|
-
|
1
|
+
# Require these to allow requiring thinkingtank outside a Rails app, e.g.
|
2
|
+
# for testing.
|
3
|
+
require 'erb'
|
4
|
+
require 'yaml'
|
5
|
+
require 'singleton'
|
6
|
+
|
7
|
+
require 'thinkingtank/indextank_client'
|
2
8
|
|
3
9
|
module ThinkingTank
|
4
10
|
class Builder
|
@@ -23,6 +29,7 @@ module ThinkingTank
|
|
23
29
|
include Singleton
|
24
30
|
attr_accessor :app_root, :client
|
25
31
|
def initialize
|
32
|
+
self.app_root = Rails.root if defined?(Rails.root)
|
26
33
|
self.app_root = RAILS_ROOT if defined?(RAILS_ROOT)
|
27
34
|
self.app_root = Merb.root if defined?(Merb)
|
28
35
|
self.app_root ||= Dir.pwd
|
@@ -31,12 +38,15 @@ module ThinkingTank
|
|
31
38
|
return unless File.exists?(path)
|
32
39
|
|
33
40
|
conf = YAML::load(ERB.new(IO.read(path)).result)[environment]
|
34
|
-
api_url = ENV['
|
35
|
-
|
41
|
+
api_url = ENV['INDEXTANK_API_URL'] || conf['api_url']
|
42
|
+
index_name = conf['index_name'] || 'default_index'
|
43
|
+
self.client = IndexTank::ApiClient.new(api_url).get_index(index_name)
|
36
44
|
end
|
37
45
|
def environment
|
38
46
|
if defined?(Merb)
|
39
47
|
Merb.environment
|
48
|
+
elsif defined?(Rails.env)
|
49
|
+
Rails.env
|
40
50
|
elsif defined?(RAILS_ENV)
|
41
51
|
RAILS_ENV
|
42
52
|
else
|
@@ -61,65 +71,3 @@ module ThinkingTank
|
|
61
71
|
end
|
62
72
|
|
63
73
|
end
|
64
|
-
|
65
|
-
class << ActiveRecord::Base
|
66
|
-
@indexable = false
|
67
|
-
def search(*args)
|
68
|
-
return indextank_search(true, *args)
|
69
|
-
end
|
70
|
-
def search_raw(*args)
|
71
|
-
return indextank_search(false, *args)
|
72
|
-
end
|
73
|
-
|
74
|
-
def define_index(name = nil, &block)
|
75
|
-
include ThinkingTank::IndexMethods
|
76
|
-
@thinkingtank_builder = ThinkingTank::Builder.new self, &block
|
77
|
-
@indexable = true
|
78
|
-
after_save :update_index
|
79
|
-
end
|
80
|
-
|
81
|
-
def is_indexable?
|
82
|
-
return @indexable
|
83
|
-
end
|
84
|
-
|
85
|
-
def thinkingtank_builder
|
86
|
-
return @thinkingtank_builder
|
87
|
-
end
|
88
|
-
|
89
|
-
private
|
90
|
-
|
91
|
-
def indextank_search(models, *args)
|
92
|
-
options = args.extract_options!
|
93
|
-
query = args.join(' ')
|
94
|
-
|
95
|
-
# transform fields in query
|
96
|
-
|
97
|
-
if options.has_key? :conditions
|
98
|
-
options[:conditions].each do |field,value|
|
99
|
-
query += " #{field}:(#{value})"
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
options.slice!(:snippet, :fetch, :function)
|
104
|
-
|
105
|
-
it = ThinkingTank::Configuration.instance.client
|
106
|
-
models = []
|
107
|
-
res = it.search("__any:(#{query.to_s}) __type:#{self.name}", options)
|
108
|
-
if models
|
109
|
-
res['results'].each do |doc|
|
110
|
-
type, docid = doc['docid'].split(" ", 2)
|
111
|
-
models << self.find(id=docid)
|
112
|
-
end
|
113
|
-
return models
|
114
|
-
else
|
115
|
-
res['results'].each do |doc|
|
116
|
-
type, docid = doc['docid'].split(" ", 2)
|
117
|
-
doc['model'] = self.find(id=docid)
|
118
|
-
end
|
119
|
-
return res
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
end
|
124
|
-
|
125
|
-
|
data/lib/thinkingtank/tasks.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
|
-
|
2
|
-
require '
|
3
|
-
require 'indextank_client'
|
1
|
+
# Load init for Rails 2, since it directly loads this file
|
2
|
+
require 'thinkingtank/init'
|
4
3
|
|
5
4
|
def load_models
|
6
5
|
app_root = ThinkingTank::Configuration.instance.app_root
|
@@ -30,19 +29,44 @@ end
|
|
30
29
|
|
31
30
|
def reindex_models
|
32
31
|
it = ThinkingTank::Configuration.instance.client
|
33
|
-
if it.
|
32
|
+
if it.nil?
|
33
|
+
puts "!!! Couldn't create a client. Does config/indextank.yml have the correct info?"
|
34
|
+
return false
|
35
|
+
end
|
36
|
+
|
37
|
+
if it.exists? and it.code
|
38
|
+
# Check for code because it.exists? may return true for a
|
39
|
+
# nonexistent index
|
34
40
|
puts "Deleting existing index"
|
35
41
|
it.delete_index()
|
36
42
|
end
|
37
43
|
puts "Creating a new empty index"
|
38
44
|
it.create_index()
|
39
|
-
puts "Waiting for the index to be ready"
|
45
|
+
puts "Waiting for the index to be ready (this might take a while)"
|
40
46
|
while not it.running?
|
47
|
+
print "."
|
48
|
+
STDOUT.flush
|
41
49
|
sleep 0.5
|
42
50
|
end
|
51
|
+
print "\n"
|
52
|
+
STDOUT.flush
|
53
|
+
|
54
|
+
|
55
|
+
subclasses = nil
|
56
|
+
if ActiveRecord::Base.respond_to?(:descendants)
|
57
|
+
# Rails 3.0.0 and higher
|
58
|
+
subclasses = ActiveRecord::Base.descendants
|
59
|
+
elsif Object.respond_to?(:subclasses_of)
|
60
|
+
subclasses = Object.subclasses_of(ActiveRecord::Base)
|
61
|
+
end
|
43
62
|
|
44
|
-
|
45
|
-
|
63
|
+
if subclasses.nil?
|
64
|
+
STDERR.puts "Couldn't detect models to index."
|
65
|
+
return false
|
66
|
+
else
|
67
|
+
subclasses.each do |klass|
|
68
|
+
reindex klass if klass.is_indexable?
|
69
|
+
end
|
46
70
|
end
|
47
71
|
end
|
48
72
|
|
@@ -54,6 +78,8 @@ def reindex(klass)
|
|
54
78
|
end
|
55
79
|
|
56
80
|
namespace :indextank do
|
81
|
+
# MUST have a description for it to show up in rake -T!
|
82
|
+
desc "Reindex all models. This deletes and recreates the index."
|
57
83
|
task :reindex => :environment do
|
58
84
|
load_models
|
59
85
|
reindex_models
|
@@ -61,5 +87,6 @@ namespace :indextank do
|
|
61
87
|
end
|
62
88
|
|
63
89
|
namespace :it do
|
90
|
+
desc "An alias for indextank:reindex"
|
64
91
|
task :reindex => "indextank:reindex"
|
65
92
|
end
|
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: thinkingtank
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
hash: 21
|
4
5
|
prerelease: false
|
5
6
|
segments:
|
6
7
|
- 0
|
7
8
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
9
|
+
- 5
|
10
|
+
version: 0.0.5
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- Flaptor
|
@@ -14,7 +15,7 @@ autorequire:
|
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date: 2010-
|
18
|
+
date: 2010-12-23 00:00:00 -02:00
|
18
19
|
default_executable:
|
19
20
|
dependencies: []
|
20
21
|
|
@@ -29,12 +30,12 @@ extensions: []
|
|
29
30
|
extra_rdoc_files: []
|
30
31
|
|
31
32
|
files:
|
32
|
-
-
|
33
|
-
- lib/indextank_client.rb
|
33
|
+
- lib/thinkingtank/indextank_client.rb
|
34
34
|
- lib/thinkingtank/init.rb
|
35
|
-
-
|
36
|
-
- tasks/rails.rake
|
35
|
+
- lib/thinkingtank/railtie.rb
|
37
36
|
- lib/thinkingtank/tasks.rb
|
37
|
+
- lib/thinkingtank/activerecord_extensions.rb
|
38
|
+
- lib/thinkingtank.rb
|
38
39
|
has_rdoc: true
|
39
40
|
homepage: http://indextank.com/
|
40
41
|
licenses: []
|
@@ -45,23 +46,27 @@ rdoc_options: []
|
|
45
46
|
require_paths:
|
46
47
|
- lib
|
47
48
|
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
48
50
|
requirements:
|
49
51
|
- - ">="
|
50
52
|
- !ruby/object:Gem::Version
|
53
|
+
hash: 3
|
51
54
|
segments:
|
52
55
|
- 0
|
53
56
|
version: "0"
|
54
57
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
55
59
|
requirements:
|
56
60
|
- - ">="
|
57
61
|
- !ruby/object:Gem::Version
|
62
|
+
hash: 3
|
58
63
|
segments:
|
59
64
|
- 0
|
60
65
|
version: "0"
|
61
66
|
requirements: []
|
62
67
|
|
63
68
|
rubyforge_project:
|
64
|
-
rubygems_version: 1.3.
|
69
|
+
rubygems_version: 1.3.7
|
65
70
|
signing_key:
|
66
71
|
specification_version: 3
|
67
72
|
summary: Thinking-Sphinx-like Indextank plugin.
|
data/README
DELETED
@@ -1,67 +0,0 @@
|
|
1
|
-
ThinkingTank
|
2
|
-
=============
|
3
|
-
|
4
|
-
ActiveRecord extension that allows to define models that should be indexed
|
5
|
-
in an existing IndexTank index. It supports a very similar syntax to
|
6
|
-
ThinkingSphinx allowing to easily port an existing project.
|
7
|
-
|
8
|
-
Every indexable model should include a define_index block in its class
|
9
|
-
definition, see the example for more details. This block supports the indexes
|
10
|
-
method and receives a field name.
|
11
|
-
|
12
|
-
Model classes now have a search method that receives one or more string
|
13
|
-
arguments with query strings (according to the query specifications) and
|
14
|
-
supports the :conditions argument as a hash from field name to query string.
|
15
|
-
|
16
|
-
In order for this extension to work you need to define a config/indextank.yml
|
17
|
-
in your application with the api_key and index_code (or index_name) settings
|
18
|
-
for each environment (similar to config/database.yml).
|
19
|
-
|
20
|
-
Indexed fields in ActiveRecord are prepended an underscore when sent to
|
21
|
-
IndexTank so if you plan to write query strings that use your field names you
|
22
|
-
will have to prepend the underscore to the field names.
|
23
|
-
|
24
|
-
In order for the ThinkingTank rake tasks to be available you need to add:
|
25
|
-
|
26
|
-
require 'thinkingtank/tasks'
|
27
|
-
|
28
|
-
to your Rakefile. You can use the following task to reindex your entire database:
|
29
|
-
|
30
|
-
rake indextank:reindex
|
31
|
-
|
32
|
-
|
33
|
-
Example
|
34
|
-
=======
|
35
|
-
|
36
|
-
Sample config/indextank.yml file:
|
37
|
-
|
38
|
-
development:
|
39
|
-
api_key: '<YOUR API KEY>'
|
40
|
-
index_code: '<INDEX CODE>'
|
41
|
-
# instead of index_code you can also use an index_name
|
42
|
-
test:
|
43
|
-
api_key: '<YOUR API KEY>'
|
44
|
-
index_code: '<INDEX CODE>'
|
45
|
-
# instead of index_code you can also use an index_name
|
46
|
-
production:
|
47
|
-
api_key: '<YOUR API KEY>'
|
48
|
-
index_code: '<INDEX CODE>'
|
49
|
-
# instead of index_code you can also use an index_name
|
50
|
-
|
51
|
-
Sample model:
|
52
|
-
class Person < ActiveRecord::Base
|
53
|
-
define_index do
|
54
|
-
indexes :name
|
55
|
-
indexes gender
|
56
|
-
indexes age
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
Sample query code:
|
61
|
-
Person.search("john")
|
62
|
-
Person.search("john OR stacey")
|
63
|
-
Person.search("stacey", :conditions => { :age => 25 } )
|
64
|
-
Person.search("james", :conditions => { :age => 25 , :gender => "female" } )
|
65
|
-
|
66
|
-
|
67
|
-
Copyright(c) 2010 Flaptor Inc.
|
data/rails/init.rb
DELETED
data/tasks/rails.rake
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), '/tasks')
|