xapian_db 1.3.5.4 → 1.3.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e0a8125904c6b19bde0907e2be6ff7ad9f319927
4
- data.tar.gz: 6ada801fee29d59e484e7813c8b6dbd1664a802b
3
+ metadata.gz: 8fcb96848f64b5fb55dee7fcd4cd2fa246c3161b
4
+ data.tar.gz: d084663854eccb8578c0cc6f8c91244034a51f37
5
5
  SHA512:
6
- metadata.gz: ecd0e5c8e4fb4cf239f71b5b3279cc2ecbfdc7c76f63e2b493e2b6e3908e14db99566edd269e582179492bd4cf40056fe44893030f82d24ab503d537730dbc8b
7
- data.tar.gz: 442bf0b4d19ca49fe230133fc03119fd3d8e6b555a0e30a8276c667a3addaf0a0613bcdbbb2165906aee28c4870db189647cccda10f972caa4eb8127f0880ae1
6
+ metadata.gz: 9887f97d274399336ff92f7ee41d9b6d9a89df483a355b28673891bd4c96acc8541548e5dc95e2cd15e90739fc72480d6bbedf1dad96de488f0a4cc12424ac44
7
+ data.tar.gz: 86a87a39b867e19bf1ba8115b94657ea924628c0a62c670bd4cc68069b590196c7414dd471e1b76937ebf4debc463c7361b67af6b1adb99bd64a8edf95dd4fb7
@@ -1,3 +1,27 @@
1
+ ##1.3.7 (January 12th, 2016)
2
+
3
+ Breaking Changes:
4
+
5
+ - search methods accept either a limit option OR page / per_page options, not both
6
+
7
+ Fixes:
8
+
9
+ - `XapianDb.database.delete_docs_of_class(klass)` now deletes docs of all descendants of `klass`, too (if tracked)
10
+
11
+ Changes:
12
+
13
+ - Ability to declare dependenices between blueprints
14
+ - Support for result ordering
15
+ - added a indexer preprocess callback to manipulate the terms that the indexer will index
16
+
17
+ ##1.3.6 (August 14th, 2015)
18
+
19
+ Changes:
20
+
21
+ - The required Ruby version is now 2.0.0 since we started using keyword parameters in method definitions
22
+ - Ability do define and handle dependencies between blueprints (see README)
23
+ - explicit order option for searches
24
+
1
25
  ##1.3.5.4 (Jan 13th, 2015)
2
26
 
3
27
  Fixes:
@@ -32,9 +32,9 @@ I tried hard but I couldn't find such a thing so I decided to write it, based on
32
32
 
33
33
  == Requirements
34
34
 
35
- * ruby 1.9.2 or newer
35
+ * ruby 2.0.0 or newer
36
36
  * rails 3.0 or newer (if you want to use it with rails)
37
- * xapian-core and xapian-ruby binaries installed
37
+ * xapian-core and xapian-ruby binaries 1.2.x installed
38
38
 
39
39
  == Installing xapian binaries
40
40
 
@@ -194,6 +194,32 @@ are ordered by relevance and - within the same relevance - by the natural sort o
194
194
  end
195
195
  end
196
196
 
197
+ You can specify a Ruby method for preprocessing the indexed terms. The method needs to be a class method that takes one argument (the terms to be indexed) and
198
+ returns a string. You can configure it globaly in the config or on a blueprint. For example, this setup will make words with accented e characters searchable
199
+ by their accentless form:
200
+
201
+ class Util
202
+ def self.strip_accents(terms)
203
+ terms.gsub(/[éèêëÉÈÊË]/, "e")
204
+ end
205
+ end
206
+
207
+ XapianDb::Config.setup do |config|
208
+ config.indexer_preprocess_callback UtilT.method(:strip_accents)
209
+ end
210
+
211
+ You may use attributes from associated objects in a blueprint; if you do that and an associated object is updated, your objects should be reindexed, too. You can tell XapnaDB about those dependencies like so:
212
+
213
+ XapianDb::DocumentBlueprint.setup(:Person) do |blueprint|
214
+ blueprint.attribue :address, :as => :json
215
+
216
+ blueprint.dependency :Address, when_changed: %i(street zip city) do |address|
217
+ Person.joins{ address }.where{ adresses.id == my{ address.id } }
218
+ end
219
+ end
220
+
221
+ The block you supply to the dependency declaration must return a collection of objects that should get reindexed, too.
222
+
197
223
  If you want to manage the (re)indexing of your objects on your own, turn off autoindexing in your blueprint:
198
224
 
199
225
  XapianDb::DocumentBlueprint.setup(:Person) do |blueprint|
@@ -246,6 +272,10 @@ You can query attributes:
246
272
 
247
273
  results = XapianDb.search "name:Foo"
248
274
 
275
+ You can force the sort order:
276
+
277
+ results = XapianDb.search "name:Foo", order: [:name]
278
+
249
279
  You can query objects of a specific class:
250
280
 
251
281
  results = Person.search "name:Foo"
@@ -105,9 +105,9 @@ module XapianDb
105
105
 
106
106
  # Update an object in the index
107
107
  # @param [Object] obj An instance of a class with a blueprint configuration
108
- def self.index(obj, commit=true)
108
+ def self.index(obj, commit=true, changed_attrs: [])
109
109
  writer = @block_writer || XapianDb::Config.writer
110
- writer.index obj, commit
110
+ writer.index obj, commit, changed_attrs: changed_attrs
111
111
  end
112
112
 
113
113
  # Remove a document from the index
@@ -119,11 +119,11 @@ module XapianDb
119
119
 
120
120
  # Update or delete a xapian document belonging to an object depending on the ignore_if logic(if present)
121
121
  # @param [Object] object An instance of a class with a blueprint configuration
122
- def self.reindex(object, commit=true)
122
+ def self.reindex(object, commit=true, changed_attrs: [])
123
123
  writer = @block_writer || XapianDb::Config.writer
124
124
  blueprint = XapianDb::DocumentBlueprint.blueprint_for object.class.name
125
125
  if blueprint.should_index?(object)
126
- writer.index object, commit
126
+ writer.index object, commit, changed_attrs: changed_attrs
127
127
  else
128
128
  writer.delete_doc_with object.xapian_id, commit
129
129
  end
@@ -191,5 +191,4 @@ module XapianDb
191
191
  @block_writer = nil
192
192
  end
193
193
  end
194
-
195
194
  end
@@ -49,7 +49,12 @@ module XapianDb
49
49
  # add the after commit logic, unless the blueprint has autoindexing turned off
50
50
  if XapianDb::DocumentBlueprint.blueprint_for(klass.name).autoindex?
51
51
  after_commit do
52
- XapianDb.reindex(self) unless self.destroyed?
52
+ unless self.destroyed?
53
+ XapianDb.reindex(self, true, changed_attrs: self.previous_changes.keys)
54
+ XapianDb::DocumentBlueprint.dependencies_for(klass.name, self.previous_changes.keys).each do |dependency|
55
+ dependency.block.call(self).each{ |model| XapianDb.reindex model, true, changed_attrs: self.previous_changes.keys }
56
+ end
57
+ end
53
58
  end
54
59
  end
55
60
 
@@ -64,7 +69,6 @@ module XapianDb
64
69
  XapianDb.reindex_class(klass, options)
65
70
  end
66
71
  end
67
-
68
72
  end
69
73
 
70
74
  # Implement the document helper methods on a module
@@ -76,7 +80,7 @@ module XapianDb
76
80
 
77
81
  # Implement access to the model id
78
82
  define_method :id do
79
- return @id unless @d.nil?
83
+ return @id unless @id.nil?
80
84
  # retrieve the class and id from data
81
85
  klass_name, id = data.split("-")
82
86
  @id = id.to_i
@@ -90,11 +94,8 @@ module XapianDb
90
94
  klass = constantize klass_name
91
95
  @indexed_object = klass.find(id.to_i)
92
96
  end
93
-
94
97
  end
95
-
96
98
  end
97
-
98
99
  end
99
100
  end
100
101
  end
@@ -32,7 +32,7 @@ module XapianDb
32
32
  end
33
33
 
34
34
  # Install delegates for the config instance variables
35
- [:database, :adapter, :writer, :stemmer, :stopper].each do |attr|
35
+ [:database, :adapter, :writer, :stemmer, :stopper, :preprocess_terms].each do |attr|
36
36
  define_method attr do
37
37
  @config.nil? ? nil : @config.instance_variable_get("@_#{attr}")
38
38
  end
@@ -183,5 +183,21 @@ module XapianDb
183
183
  @_enabled_query_flags.delete flag
184
184
  end
185
185
 
186
+ # Set the indexer preprocess callback.
187
+ # @param [Method] method a class method; needs to take one parameter and return a string.
188
+ # @example
189
+ # class Util
190
+ # def self.strip_accents(terms)
191
+ # terms.gsub(/[éèêëÉÈÊË]/, "e")
192
+ # end
193
+ # end
194
+ #
195
+ # XapianDb::Config.setup do |config|
196
+ # config.indexer_preprocess_callback Util.method(:strip_accents)
197
+ # end
198
+ def indexer_preprocess_callback(method)
199
+ @_preprocess_terms = method
200
+ end
201
+
186
202
  end
187
203
  end
@@ -35,10 +35,19 @@ module XapianDb
35
35
  true
36
36
  end
37
37
 
38
- # Delete all docs of a specific class
38
+ # Delete all docs of a specific class.
39
+ #
40
+ # If `klass` tracks its descendants, then docs of any subclasses will be deleted, too.
41
+ # (ActiveRecord does this by default; the gem 'descendants_tracker' offers an alternative.)
42
+ #
39
43
  # @param [Class] klass A class that has a {XapianDb::DocumentBlueprint} configuration
40
44
  def delete_docs_of_class(klass)
41
45
  writer.delete_document("C#{klass}")
46
+ if klass.respond_to? :descendants
47
+ klass.descendants.each do |subclass|
48
+ writer.delete_document("C#{subclass}")
49
+ end
50
+ end
42
51
  true
43
52
  end
44
53
 
@@ -73,6 +82,12 @@ module XapianDb
73
82
  enquiry.query = query
74
83
  sort_indices = opts.delete :sort_indices
75
84
  sort_decending = opts.delete :sort_decending
85
+ order = opts.delete :order
86
+ raise ArgumentError.new "you can't use sort_indices and order, only one of them" if sort_indices && order
87
+
88
+ if order
89
+ sort_indices = order.map{ |attr_name| XapianDb::DocumentBlueprint.value_number_for attr_name.to_sym }
90
+ end
76
91
 
77
92
  sorter = Xapian::MultiValueKeyMaker.new
78
93
  if sort_indices
@@ -80,7 +95,7 @@ module XapianDb
80
95
  enquiry.set_sort_by_key_then_relevance(sorter, sort_decending)
81
96
  else
82
97
  sorter.add_value DocumentBlueprint.value_number_for(:natural_sort_order)
83
- enquiry.set_sort_by_relevance_then_key sorter, true
98
+ enquiry.set_sort_by_relevance_then_key sorter, false
84
99
  end
85
100
 
86
101
  opts[:spelling_suggestion] = @query_parser.spelling_suggestion
@@ -50,6 +50,7 @@ module XapianDb
50
50
  # We can always do a field search on the name of the indexed class
51
51
  @searchable_prefixes << "indexed_class"
52
52
  @attributes = @blueprints.values.map { |blueprint| blueprint.attribute_names}.flatten.compact.uniq.sort || []
53
+ blueprint
53
54
  end
54
55
 
55
56
  # reset the blueprint setup
@@ -66,11 +67,17 @@ module XapianDb
66
67
  # Get all configured classes
67
68
  # @return [Array<Class>]
68
69
  def configured_classes
69
- if @blueprints
70
- @blueprints.keys.map {|class_name| XapianDb::Utilities.constantize(class_name) }
71
- else
72
- []
73
- end
70
+ if @blueprints
71
+ @blueprints.keys.map {|class_name| XapianDb::Utilities.constantize(class_name) }
72
+ else
73
+ []
74
+ end
75
+ end
76
+
77
+ def dependencies_for(klass_name, changed_attrs)
78
+ @blueprints.values.map(&:dependencies)
79
+ .flatten
80
+ .select{ |dependency| dependency.dependent_on == klass_name && dependency.interested_in?(changed_attrs) }
74
81
  end
75
82
 
76
83
  # Get the blueprint for a class
@@ -167,7 +174,6 @@ module XapianDb
167
174
  end
168
175
  end
169
176
  end
170
-
171
177
  end
172
178
 
173
179
  # ---------------------------------------------------------------------------------
@@ -258,15 +264,17 @@ module XapianDb
258
264
  # Blueprint DSL methods
259
265
  # ---------------------------------------------------------------------------------
260
266
 
261
- attr_reader :lazy_base_query, :_natural_sort_order
267
+ attr_reader :lazy_base_query, :_natural_sort_order, :dependencies
262
268
 
263
269
  # Construct the blueprint
264
270
  def initialize
265
271
  @attributes_hash = {}
266
272
  @indexed_methods_hash = {}
267
273
  @type_map = {}
274
+ @dependencies = []
268
275
  @_natural_sort_order = :id
269
276
  @autoindex = true
277
+ @indexer_preprocess_callback = nil
270
278
  end
271
279
 
272
280
  # Set the adapter
@@ -377,7 +385,7 @@ module XapianDb
377
385
  @ignore_expression = block
378
386
  end
379
387
 
380
- # Define a base query to select one or all objects of the indexed class. The reason for a
388
+ # Define a base query to select one or all objects of the indexed class. The reason for a
381
389
  # base query is to optimize the query avoiding th 1+n problematic. The base query should only
382
390
  # include joins(...) and includes(...) calls.
383
391
  # @param [expression] a base query expression
@@ -400,6 +408,33 @@ module XapianDb
400
408
  @_natural_sort_order = name || block
401
409
  end
402
410
 
411
+ def dependency(klass_name, when_changed: [], &block)
412
+ @dependencies << Dependency.new(klass_name.to_s, when_changed, block)
413
+ end
414
+
415
+ # Set the indexer preprocess callback.
416
+ # @param [Method] method a class method; needs to take one parameter and return a string.
417
+ # @example
418
+ # class Util
419
+ # def self.strip_accents(terms)
420
+ # terms.gsub(/[éèêëÉÈÊË]/, "e")
421
+ # end
422
+ # end
423
+ #
424
+ # XapianDb::DocumentBlueprint.setup(:IndexedObject) do |blueprint|
425
+ # blueprint.attribute :name
426
+ # blueprint.indexer_preprocess_callback Util.method(:strip_accents)
427
+ # end
428
+ def indexer_preprocess_callback(method)
429
+ @indexer_preprocess_callback = method
430
+ end
431
+
432
+ # Reader for indexer_preprocess_callback.
433
+ # Returns the terms preprocessing method for this blueprint, the global method from config or nil.
434
+ def preprocess_terms
435
+ @indexer_preprocess_callback || XapianDb::Config.preprocess_terms
436
+ end
437
+
403
438
  # Options for an indexed method
404
439
  class IndexOptions
405
440
 
@@ -414,7 +449,24 @@ module XapianDb
414
449
  @no_split = options[:no_split]
415
450
  @block = options[:block]
416
451
  end
452
+ end
453
+
454
+ class Dependency
455
+
456
+ attr_reader :dependent_on, :trigger_attributes, :block
457
+
458
+ # Constructor
459
+ # @param [String] klass_name Name of the dependent class
460
+ # @param [Array] trigger_attributes List of attributes to watch for changes (if empty, triggers on any change)
461
+ # @option [Block] block Block that is called when changes are detected; the block must return an array of indexeable objects
462
+ def initialize(klass_name, trigger_attributes, block)
463
+ @dependent_on, @trigger_attributes, @block = klass_name, trigger_attributes.map(&:to_s), block
464
+ end
417
465
 
466
+ def interested_in?(changed_attrs)
467
+ return true if @trigger_attributes.empty?
468
+ (@trigger_attributes & changed_attrs).any?
469
+ end
418
470
  end
419
471
 
420
472
  private
@@ -431,7 +483,5 @@ module XapianDb
431
483
  @reserved_method_names ||= Xapian::Document.instance_methods
432
484
  @reserved_method_names.include?(attr_name.to_sym)
433
485
  end
434
-
435
486
  end
436
-
437
487
  end
@@ -13,7 +13,7 @@ module XapianDb
13
13
  def index_task(options)
14
14
  klass = constantize options[:class]
15
15
  obj = klass.respond_to?(:get) ? klass.get(options[:id]) : klass.find(options[:id])
16
- DirectWriter.index obj
16
+ DirectWriter.index obj, true, changed_attrs: options[:changed_attrs]
17
17
  end
18
18
 
19
19
  def delete_doc_task(options)
@@ -24,7 +24,6 @@ module XapianDb
24
24
  klass = constantize options[:class]
25
25
  DirectWriter.reindex_class klass, :verbose => false
26
26
  end
27
-
28
27
  end
29
28
  end
30
- end
29
+ end
@@ -18,8 +18,8 @@ module XapianDb
18
18
 
19
19
  # Update an object in the index
20
20
  # @param [Object] obj An instance of a class with a blueprint configuration
21
- def index(obj, commit=true)
22
- beanstalk.put( {:task => "index_task", :class => obj.class.name, :id => obj.id }.to_json )
21
+ def index(obj, commit=true, changed_attrs: [])
22
+ beanstalk.put( { :task => "index_task", :class => obj.class.name, :id => obj.id, :changed_attrs => changed_attrs }.to_json )
23
23
  end
24
24
 
25
25
  # Remove an object from the index
@@ -17,11 +17,11 @@ module XapianDb
17
17
  class << self
18
18
 
19
19
  # Update an object in the index
20
- # @param [Object] obj An instance of a class with a blueprint configuration
21
- def index(obj, commit=true)
22
- blueprint = XapianDb::DocumentBlueprint.blueprint_for(obj.class.name)
20
+ # @param [Object] object An instance of a class with a blueprint configuration
21
+ def index(object, commit=true, changed_attrs: [])
22
+ blueprint = XapianDb::DocumentBlueprint.blueprint_for(object.class.name)
23
23
  indexer = XapianDb::Indexer.new(XapianDb.database, blueprint)
24
- doc = indexer.build_document_for(obj)
24
+ doc = indexer.build_document_for(object)
25
25
  XapianDb.database.store_doc(doc)
26
26
  XapianDb.database.commit if commit
27
27
  end
@@ -35,10 +35,10 @@ module XapianDb
35
35
 
36
36
  # Update or delete a xapian document belonging to an object depending on the ignore_if logic(if present)
37
37
  # @param [Object] object An instance of a class with a blueprint configuration
38
- def reindex(object, commit=true)
38
+ def reindex(object, commit=true, changed_attrs: [])
39
39
  blueprint = XapianDb::DocumentBlueprint.blueprint_for object.class.name
40
40
  if blueprint.should_index?(object)
41
- index object, commit
41
+ index object, commit, changed_attrs: changed_attrs
42
42
  else
43
43
  delete_doc_with object.xapian_id, commit
44
44
  end
@@ -12,7 +12,7 @@ module XapianDb
12
12
 
13
13
  # Update an object in the index
14
14
  # @param [Object] obj An instance of a class with a blueprint configuration
15
- def index(obj, commit=true); end
15
+ def index(obj, commit=true, changed_attrs: []); end
16
16
 
17
17
  # Remove an object from the index
18
18
  # @param [String] xapian_id The document id
@@ -28,4 +28,4 @@ module XapianDb
28
28
  end
29
29
  end
30
30
  end
31
- end
31
+ end
@@ -22,7 +22,7 @@ module XapianDb
22
22
  def index(options)
23
23
  klass = constantize options['class']
24
24
  obj = klass.respond_to?('get') ? klass.get(options['id']) : klass.find(options['id'])
25
- DirectWriter.index obj
25
+ DirectWriter.index obj, true, changed_attrs: options[:changed_attrs]
26
26
  end
27
27
 
28
28
  def delete_doc(options)
@@ -34,7 +34,6 @@ module XapianDb
34
34
  DirectWriter.reindex_class klass, :verbose => false
35
35
  end
36
36
  end
37
-
38
37
  end
39
38
  end
40
39
  end
@@ -12,8 +12,8 @@ module XapianDb
12
12
 
13
13
  # Update an object in the index
14
14
  # @param [Object] obj An instance of a class with a blueprint configuration
15
- def index(obj, commit=true)
16
- Resque.enqueue worker_class, :index, :class => obj.class.name, :id => obj.id
15
+ def index(obj, commit=true, changed_attrs: [])
16
+ Resque.enqueue worker_class, :index, :class => obj.class.name, :id => obj.id, changed_attrs: changed_attrs
17
17
  end
18
18
 
19
19
  # Remove an object from the index
@@ -33,7 +33,6 @@ module XapianDb
33
33
  end
34
34
  private :worker_class
35
35
  end
36
-
37
36
  end
38
37
  end
39
38
  end
@@ -26,7 +26,7 @@ module XapianDb
26
26
  def index(options)
27
27
  klass = constantize options['class']
28
28
  obj = klass.respond_to?('get') ? klass.get(options['id']) : klass.find(options['id'])
29
- DirectWriter.index obj
29
+ DirectWriter.index obj, true, changed_attrs: options[:changed_attrs]
30
30
  end
31
31
 
32
32
  def delete_doc(options)
@@ -16,8 +16,8 @@ module XapianDb
16
16
 
17
17
  # Update an object in the index
18
18
  # @param [Object] obj An instance of a class with a blueprint configuration
19
- def index(obj, commit=true)
20
- Sidekiq::Client.enqueue worker_class, :index, :class => obj.class.name, :id => obj.id
19
+ def index(obj, commit=true, changed_attrs: [])
20
+ Sidekiq::Client.enqueue worker_class, :index, :class => obj.class.name, :id => obj.id, :changed_attrs => changed_attrs
21
21
  end
22
22
 
23
23
  # Remove an object from the index
@@ -37,7 +37,6 @@ module XapianDb
37
37
  end
38
38
  private :worker_class
39
39
  end
40
-
41
40
  end
42
41
  end
43
42
  end
@@ -20,7 +20,7 @@ module XapianDb
20
20
 
21
21
  # Update an object in the index
22
22
  # @param [Object] obj An instance of a class with a blueprint configuration
23
- def index(obj, commit=false)
23
+ def index(obj, commit=false, changed_attrs: [])
24
24
  @index_requests << obj
25
25
  end
26
26
 
@@ -45,8 +45,6 @@ module XapianDb
45
45
  @delete_requests.each { |xapian_id| writer.delete_doc_with xapian_id, false }
46
46
  XapianDb.database.commit
47
47
  end
48
-
49
48
  end
50
-
51
49
  end
52
- end
50
+ end
@@ -86,6 +86,7 @@ module XapianDb
86
86
  values = get_values_to_index_from obj
87
87
  values.each do |value|
88
88
  terms = value.to_s.downcase
89
+ terms = @blueprint.preprocess_terms.call(terms) if @blueprint.preprocess_terms
89
90
  terms = split(terms) if XapianDb::Config.term_splitter_count > 0 && !options.no_split
90
91
  # Add value with field name
91
92
  term_generator.index_text(terms, options.weight, "X#{method.upcase}") if options.prefixed
@@ -46,6 +46,7 @@ module XapianDb
46
46
  # @param [Hash] options
47
47
  # @option options [Integer] :db_size The current size (nr of docs) of the database
48
48
  # @option options [Integer] :limit The maximum number of documents to retrieve
49
+ # @option options [Integer] :offset The index of the first result to retrieve
49
50
  # @option options [Integer] :page (1) The page number to retrieve
50
51
  # @option options [Integer] :per_page (10) How many docs per page? Ignored if a limit option is given
51
52
  # @option options [String] :spelling_suggestion (nil) The spelling corrected query (if a language is configured)
@@ -56,25 +57,32 @@ module XapianDb
56
57
  db_size = params.delete :db_size
57
58
  @spelling_suggestion = params.delete :spelling_suggestion
58
59
  limit = params.delete :limit
60
+ offset = params.delete :offset
59
61
  page = params.delete :page
60
62
  per_page = params.delete :per_page
61
63
  raise ArgumentError.new "unsupported options for resultset: #{params}" if params.size > 0
62
64
  raise ArgumentError.new "db_size option is required" unless db_size
63
65
 
66
+ unless (page.nil? && per_page.nil?) || (limit.nil? && offset.nil?)
67
+ raise ArgumentError.new "Impossible combination of parameters. Either pass page and/or per_page, or limit and/or offset."
68
+ end
69
+
70
+ calculated_page = offset.nil? || limit.nil? ? nil : (offset.to_f / limit.to_f) + 1
71
+
64
72
  limit = limit.nil? ? db_size : limit.to_i
65
- per_page = per_page.nil? ? limit : per_page.to_i
66
- page = page.nil? ? 1 : page.to_i
67
- offset = (page - 1) * per_page
68
- count = offset + per_page < limit ? per_page : limit - offset
73
+ per_page = per_page.nil? ? limit.to_i : per_page.to_i
74
+ page = page.nil? ? (calculated_page.nil? ? 1 : calculated_page) : page.to_i
75
+ offset = offset.nil? ? (page - 1) * per_page : offset.to_i
76
+ count = per_page < limit ? per_page : limit
69
77
 
78
+ return build_empty_resultset if (page - 1) * per_page > db_size
70
79
  result_window = enquiry.mset(offset, count)
71
80
  @hits = result_window.matches_estimated
72
81
  return build_empty_resultset if @hits == 0
73
- raise ArgumentError.new "page #{@page} does not exist" if @hits > 0 && offset >= limit
74
82
 
75
83
  self.replace result_window.matches.map{|match| decorate(match).document}
76
84
  @total_pages = (@hits / per_page.to_f).ceil
77
- @current_page = page
85
+ @current_page = (page == page.to_i) ? page.to_i : page
78
86
  @limit_value = per_page
79
87
  end
80
88
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xapian_db
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.5.4
4
+ version: 1.3.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gernot Kogler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-13 00:00:00.000000000 Z
11
+ date: 2016-01-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: daemons
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: 2.3.1
47
+ version: 2.99.0
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: 2.3.1
54
+ version: 2.99.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: simplecov
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -142,14 +142,14 @@ dependencies:
142
142
  requirements:
143
143
  - - '='
144
144
  - !ruby/object:Gem::Version
145
- version: 1.2.15.1
145
+ version: 1.2.22
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - '='
151
151
  - !ruby/object:Gem::Version
152
- version: 1.2.15.1
152
+ version: 1.2.22
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: pry-rails
155
155
  requirement: !ruby/object:Gem::Requirement
@@ -164,6 +164,20 @@ dependencies:
164
164
  - - ">="
165
165
  - !ruby/object:Gem::Version
166
166
  version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: descendants_tracker
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
167
181
  description: XapianDb is a ruby gem that combines features of nosql databases and
168
182
  fulltext indexing. It is based on Xapian, an efficient and powerful indexing library
169
183
  email: gernot.kogler (at) garaio (dot) com
@@ -239,7 +253,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
239
253
  requirements:
240
254
  - - ">="
241
255
  - !ruby/object:Gem::Version
242
- version: '0'
256
+ version: 2.0.0
243
257
  required_rubygems_version: !ruby/object:Gem::Requirement
244
258
  requirements:
245
259
  - - ">="