xapian_db 0.5.7 → 0.5.8

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ##0.5.8 (March 22th, 2011)
2
+
3
+ Fixes:
4
+
5
+ - automatic reindexing of a changed object now works when using beanstalk and the worker rake task
6
+
7
+ Features:
8
+
9
+ - support for transactions (see the README for details)
10
+
1
11
  ##0.5.7 (March 7th, 2011)
2
12
 
3
13
  Fixes:
data/README.rdoc CHANGED
@@ -116,6 +116,14 @@ You may add a filter expression to exclude objects from the index. This is handy
116
116
  blueprint.ignore_if {active == false}
117
117
  end
118
118
 
119
+ You can override the global adapter configuration in a specific blueprint. Let's say you use ActiveRecord, but you have
120
+ one more class that is not stored in the database, but you want it to be indexed:
121
+
122
+ XapianDb::DocumentBlueprint.setup(SpecialClass) do |blueprint|
123
+ blueprint.adapter :generic
124
+ blueprint.index :some_stuff
125
+ end
126
+
119
127
  place these configurations either into the corresponding class or - I prefer to have the index configurations outside
120
128
  the models - into the file config/xapian_blueprints.rb.
121
129
 
@@ -226,6 +234,16 @@ A global facet search always groups the results by the class of the indexed obje
226
234
 
227
235
  At the class level, any attribute can be used for a facet query.
228
236
 
237
+ === Transactions
238
+
239
+ You can execute a block of code inside a XapianDb transaction. This ensures that the changed objects in your block will get reindexed
240
+ only if the block does not raise an exception.
241
+
242
+ XapianDb.transaction do
243
+ object1.save
244
+ object2.save
245
+ end
246
+
229
247
  == Production setup
230
248
 
231
249
  Since Xapian allows only one database instance to write to the index, the default setup of XapianDb will not work
@@ -10,7 +10,7 @@ module XapianDb
10
10
  # This adapter does the following:
11
11
  # - adds the instance method <code>xapian_id</code> to an indexed class
12
12
  # - adds the class method <code>rebuild_xapian_index</code> to an indexed class
13
- # - adds an after save block to an indexed class to update the index
13
+ # - adds an after commit block to an indexed class to update the index
14
14
  # - adds an after destroy block to an indexed class to update the index
15
15
  # - adds the instance method <code>indexed_object</code> to the module that will be included
16
16
  # in every found xapian document
@@ -38,24 +38,24 @@ module XapianDb
38
38
  klass.class_eval do
39
39
 
40
40
  # add the after save logic
41
- after_save do
41
+ after_commit do
42
42
  blueprint = XapianDb::DocumentBlueprint.blueprint_for klass
43
43
  if blueprint.should_index?(self)
44
- XapianDb::Config.writer.index(self)
44
+ XapianDb.index(self)
45
45
  else
46
- XapianDb::Config.writer.unindex(self)
46
+ XapianDb.unindex(self)
47
47
  end
48
48
  end
49
49
 
50
50
  # add the after destroy logic
51
51
  after_destroy do
52
- XapianDb::Config.writer.unindex(self)
52
+ XapianDb.unindex(self)
53
53
  end
54
54
 
55
55
  # Add a method to reindex all models of this class
56
56
  define_singleton_method(:rebuild_xapian_index) do |options={}|
57
57
  options[:primary_key] = klass.primary_key
58
- XapianDb::Config.writer.reindex_class(klass, options)
58
+ XapianDb.reindex_class(klass, options)
59
59
  end
60
60
  end
61
61
 
@@ -40,21 +40,21 @@ module XapianDb
40
40
  after :save do
41
41
  blueprint = XapianDb::DocumentBlueprint.blueprint_for klass
42
42
  if blueprint.should_index?(self)
43
- XapianDb::Config.writer.index(self)
43
+ XapianDb.index(self)
44
44
  else
45
- XapianDb::Config.writer.unindex(self)
45
+ XapianDb.unindex(self)
46
46
  end
47
47
  end
48
48
 
49
49
  # add the after destroy logic
50
50
  after :destroy do
51
- XapianDb::Config.writer.unindex(self)
51
+ XapianDb.unindex(self)
52
52
  end
53
53
 
54
54
  # Add a method to reindex all models of this class
55
55
  define_singleton_method(:rebuild_xapian_index) do |options={}|
56
56
  options[:primary_key] = klass.serial.name
57
- XapianDb::Config.writer.reindex_class(self, options)
57
+ XapianDb.reindex_class(self, options)
58
58
  end
59
59
  end
60
60
 
@@ -12,6 +12,8 @@ module XapianDb
12
12
  # @author Gernot Kogler
13
13
  class Config
14
14
 
15
+ include XapianDb::Utilities
16
+
15
17
  # ---------------------------------------------------------------------------------
16
18
  # Singleton methods
17
19
  # ---------------------------------------------------------------------------------
@@ -48,7 +50,6 @@ module XapianDb
48
50
  # DSL methods
49
51
  # ---------------------------------------------------------------------------------
50
52
 
51
- #
52
53
  attr_reader :_database, :_adapter, :_writer, :_beanstalk_daemon, :_stemmer, :_stopper
53
54
 
54
55
  # Set the global database to use
@@ -108,16 +109,9 @@ module XapianDb
108
109
  # end
109
110
  # see {LANGUAGE_MAP} for supported languages
110
111
  def language(lang)
111
- key = lang.to_sym
112
- @_stemmer = XapianDb::Repositories::Stemmer.stemmer_for key
113
- key == :none ? @_stopper = nil : @_stopper = XapianDb::Repositories::Stopper.stopper_for(key)
114
- end
115
-
116
- private
117
-
118
- # TODO: move this to a helper module
119
- def camelize(string)
120
- string.split(/[^a-z0-9]/i).map{|w| w.capitalize}.join
112
+ lang ||= :none
113
+ @_stemmer = XapianDb::Repositories::Stemmer.stemmer_for lang
114
+ @_stopper = lang == :none ? nil : XapianDb::Repositories::Stopper.stopper_for(lang)
121
115
  end
122
116
 
123
117
  end
@@ -19,6 +19,8 @@ module XapianDb
19
19
  # @author Gernot Kogler
20
20
  class DocumentBlueprint
21
21
 
22
+ include XapianDb::Utilities
23
+
22
24
  # ---------------------------------------------------------------------------------
23
25
  # Singleton methods
24
26
  # ---------------------------------------------------------------------------------
@@ -295,13 +297,6 @@ module XapianDb
295
297
  @reserved_method_names.include?(attr_name.to_sym)
296
298
  end
297
299
 
298
- private
299
-
300
- # TODO: move this to a helper module
301
- def camelize(string)
302
- string.split(/[^a-z0-9]/i).map{|w| w.capitalize}.join
303
- end
304
-
305
300
  end
306
301
 
307
302
  end
@@ -0,0 +1,51 @@
1
+ # encoding: utf-8
2
+
3
+ # This writer collects index change requests but does not submit them immediately to the database.
4
+ # The index changes are applied when the commit method is called.
5
+ # This writer is intended for internal use only. Do not use it in a xapian configuration!
6
+ # @author Gernot Kogler
7
+
8
+ module XapianDb
9
+ module IndexWriters
10
+
11
+ class TransactionalWriter
12
+
13
+ attr_reader :index_requests, :unindex_requests
14
+
15
+ # Constructor
16
+ def initialize
17
+ @index_requests = []
18
+ @unindex_requests = []
19
+ end
20
+
21
+ # Update an object in the index
22
+ # @param [Object] obj An instance of a class with a blueprint configuration
23
+ def index(obj)
24
+ @index_requests << obj
25
+ end
26
+
27
+ # Remove an object from the index
28
+ # @param [Object] obj An instance of a class with a blueprint configuration
29
+ def unindex(obj)
30
+ @unindex_requests << obj
31
+ end
32
+
33
+ # Reindex all objects of a given class
34
+ # @param [Class] klass The class to reindex
35
+ # @param [Hash] options Options for reindexing
36
+ # @option options [Boolean] :verbose (false) Should the reindexing give status informations?
37
+ def reindex_class(klass, options={})
38
+ raise "rebuild_xapian_index is not supported in transactions"
39
+ end
40
+
41
+ # Commit all pending changes to the database
42
+ # @param [DirectWriter, BeanstalkWriter] writer The writer to use
43
+ def commit_using(writer)
44
+ @index_requests.each { |obj| writer.index obj }
45
+ @unindex_requests.each { |obj| writer.unindex obj }
46
+ end
47
+
48
+ end
49
+
50
+ end
51
+ end
@@ -34,10 +34,10 @@ module XapianDb
34
34
  else
35
35
  config.database File.expand_path @database_path
36
36
  end
37
- config.adapter @adapter.to_sym
38
- config.writer @writer.to_sym
37
+ config.adapter @adapter.try(:to_sym)
38
+ config.writer @writer.try(:to_sym)
39
39
  config.beanstalk_daemon_url @beanstalk_daemon
40
- config.language @language
40
+ config.language @language.try(:to_sym)
41
41
  end
42
42
 
43
43
  end
@@ -66,7 +66,6 @@ module XapianDb
66
66
  @adapter = :active_record
67
67
  @writer = :direct
68
68
  @beanstalk_daemon = nil
69
- @language = :en
70
69
  end
71
70
 
72
71
  end
@@ -0,0 +1,16 @@
1
+ # encoding: utf-8
2
+
3
+ # Collection of utility methods
4
+ # @author Gernot Kogler
5
+ module XapianDb
6
+ module Utilities
7
+
8
+ # Convert a string to camel case
9
+ # @param [String] The string to camelize
10
+ # @return [String] The camelized string
11
+ def camelize(string)
12
+ string.split(/[^a-z0-9]/i).map{|w| w.capitalize}.join
13
+ end
14
+
15
+ end
16
+ end
data/lib/xapian_db.rb CHANGED
@@ -34,6 +34,7 @@ module XapianDb
34
34
  # for available options
35
35
  def self.setup(&block)
36
36
  XapianDb::Config.setup(&block)
37
+ @writer = XapianDb::Config.writer
37
38
  end
38
39
 
39
40
  # Create a database
@@ -84,6 +85,26 @@ module XapianDb
84
85
  XapianDb::Config.database.facets(expression)
85
86
  end
86
87
 
88
+ # Update an object in the index
89
+ # @param [Object] obj An instance of a class with a blueprint configuration
90
+ def self.index(obj)
91
+ @writer.index obj
92
+ end
93
+
94
+ # Remove an object from the index
95
+ # @param [Object] obj An instance of a class with a blueprint configuration
96
+ def self.unindex(obj)
97
+ @writer.unindex obj
98
+ end
99
+
100
+ # Reindex all objects of a given class
101
+ # @param [Class] klass The class to reindex
102
+ # @param [Hash] options Options for reindexing
103
+ # @option options [Boolean] :verbose (false) Should the reindexing give status informations?
104
+ def self.reindex_class(klass, options={})
105
+ @writer.reindex_class klass, options
106
+ end
107
+
87
108
  # Rebuild the xapian index for all configured blueprints
88
109
  # @param [Hash] options Options for reindexing
89
110
  # @option options [Boolean] :verbose (false) Should the reindexing give status informations?
@@ -97,11 +118,32 @@ module XapianDb
97
118
  true
98
119
  end
99
120
 
121
+ # Execute a block as a transaction
122
+ def self.transaction(&block)
123
+ # Temporarily use the transactional writer
124
+ @writer = XapianDb::IndexWriters::TransactionalWriter.new
125
+ begin
126
+ block.call
127
+ @writer.commit_using XapianDb::Config.writer
128
+ rescue Exception => ex
129
+ msg = "error in XapianDb transaction block: #{ex}, transaction aborted"
130
+ if defined?(Rails)
131
+ Rails.logger.error msg
132
+ else
133
+ puts msg
134
+ end
135
+ ensure
136
+ # switch back to the configured writer
137
+ @writer = XapianDb::Config.writer
138
+ end
139
+ end
140
+
100
141
  end
101
142
 
102
- do_not_require = %w(update_stopwords.rb railtie.rb base_adapter.rb beanstalk_writer.rb)
143
+ do_not_require = %w(update_stopwords.rb railtie.rb base_adapter.rb beanstalk_writer.rb utilities.rb)
103
144
  files = Dir.glob("#{File.dirname(__FILE__)}/**/*.rb").reject{|path| do_not_require.include?(File.basename(path))}
104
- # Require the base adapter first
145
+ # Require these first
146
+ require "#{File.dirname(__FILE__)}/xapian_db/utilities"
105
147
  require "#{File.dirname(__FILE__)}/xapian_db/adapters/base_adapter"
106
148
  files.each {|file| require file}
107
149
 
metadata CHANGED
@@ -1,8 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xapian_db
3
3
  version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: 0.5.7
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 5
8
+ - 8
9
+ version: 0.5.8
6
10
  platform: ruby
7
11
  authors:
8
12
  - Gernot Kogler
@@ -10,7 +14,7 @@ autorequire:
10
14
  bindir: bin
11
15
  cert_chain: []
12
16
 
13
- date: 2011-03-07 00:00:00 +01:00
17
+ date: 2011-03-23 00:00:00 +01:00
14
18
  default_executable:
15
19
  dependencies:
16
20
  - !ruby/object:Gem::Dependency
@@ -21,6 +25,10 @@ dependencies:
21
25
  requirements:
22
26
  - - ">="
23
27
  - !ruby/object:Gem::Version
28
+ segments:
29
+ - 2
30
+ - 3
31
+ - 1
24
32
  version: 2.3.1
25
33
  type: :development
26
34
  version_requirements: *id001
@@ -32,6 +40,10 @@ dependencies:
32
40
  requirements:
33
41
  - - ">="
34
42
  - !ruby/object:Gem::Version
43
+ segments:
44
+ - 0
45
+ - 3
46
+ - 7
35
47
  version: 0.3.7
36
48
  type: :development
37
49
  version_requirements: *id002
@@ -43,6 +55,10 @@ dependencies:
43
55
  requirements:
44
56
  - - ">="
45
57
  - !ruby/object:Gem::Version
58
+ segments:
59
+ - 1
60
+ - 1
61
+ - 0
46
62
  version: 1.1.0
47
63
  type: :development
48
64
  version_requirements: *id003
@@ -65,6 +81,7 @@ files:
65
81
  - lib/xapian_db/index_writers/beanstalk_worker.rb
66
82
  - lib/xapian_db/index_writers/beanstalk_writer.rb
67
83
  - lib/xapian_db/index_writers/direct_writer.rb
84
+ - lib/xapian_db/index_writers/transactional_writer.rb
68
85
  - lib/xapian_db/indexer.rb
69
86
  - lib/xapian_db/query_parser.rb
70
87
  - lib/xapian_db/railtie.rb
@@ -86,6 +103,7 @@ files:
86
103
  - lib/xapian_db/stopwords/ru.txt
87
104
  - lib/xapian_db/stopwords/sv.txt
88
105
  - lib/xapian_db/stopwords/update_stopwords.rb
106
+ - lib/xapian_db/utilities.rb
89
107
  - lib/xapian_db.rb
90
108
  - tasks/beanstalk_worker.rake
91
109
  - xapian_source/xapian-bindings-1.2.4.tar.gz
@@ -113,17 +131,23 @@ required_ruby_version: !ruby/object:Gem::Requirement
113
131
  requirements:
114
132
  - - ">="
115
133
  - !ruby/object:Gem::Version
134
+ segments:
135
+ - 0
116
136
  version: "0"
117
137
  required_rubygems_version: !ruby/object:Gem::Requirement
118
138
  none: false
119
139
  requirements:
120
140
  - - ">="
121
141
  - !ruby/object:Gem::Version
142
+ segments:
143
+ - 1
144
+ - 3
145
+ - 6
122
146
  version: 1.3.6
123
147
  requirements: []
124
148
 
125
149
  rubyforge_project:
126
- rubygems_version: 1.5.0
150
+ rubygems_version: 1.3.7
127
151
  signing_key:
128
152
  specification_version: 3
129
153
  summary: Ruby library to use a Xapian db as a key/value store with high performance fulltext search