Skip to content

Commit

Permalink
added more tests allow for modified sorting
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanong committed Jul 18, 2011
1 parent eac2da8 commit c27de4a
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 45 deletions.
3 changes: 1 addition & 2 deletions README.md
Expand Up @@ -138,9 +138,8 @@ River.geo_near([-73.99756,40.73083], :page => 1)
#
# both return a GeoNearResults, which is really just a modified Array
# #per really just #page but just moves the options around
rivers = River.geo_near([-73.99756,40.73083]).sort_by!{|r| r.modified_distance}
rivers = River.geo_near([-73.99756,40.73083]).sort_by!{|r| r.geo[:distance] * r.multiplier }
rivers = rivers.per(25).page(1)
rivers = rivers.page(5, :original => 1) # by adding the original option you can re-paginate to any area.
rivers.reset! # resets the object to it is original state right after query.
```

Expand Down
66 changes: 30 additions & 36 deletions lib/mongoid_spacial/spacial/geo_near_results.rb
@@ -1,18 +1,17 @@
module Mongoid
module Spacial
class GeoNearResults < Array
attr_reader :stats, :document, :_original_array
attr_reader :stats, :document, :_original_array, :_original_opts
attr_accessor :opts

def initialize(document,results,opts = {})
raise "class must include Mongoid::Spacial::Document" unless document.respond_to?(:spacial_fields_indexed)
@document = document
@opts = opts
@_original_opts = opts.clone
@stats = results['stats'] || {}
@opts[:skip] ||= 0
@opts[:total_entries] = opts[:query]["num"] || @stats['nscanned']
@limit_value = opts[:per_page]
@current_page = opts[:page]

@_original_array = results['results'].collect do |result|
res = Mongoid::Factory.from_db(@document, result.delete('obj'))
Expand Down Expand Up @@ -40,47 +39,31 @@ def initialize(document,results,opts = {})
end
res
end

if @opts[:page]
start = (@opts[:page]-1)*@opts[:per_page] # assuming current_page is 1 based.
super(@_original_array[@opts[:skip]+start, @opts[:per_page]] || [])
@_paginated_array = @_original_array.clone
super(@_paginated_array[@opts[:skip]+start, @opts[:per_page]] || [])
else
super(@_original_array[@opts[:skip]..-1] || [])
end
end

def page(page, options = {})
new_collection = self.clone
original = options.delete(:original)
new_collection.opts.merge!(options)
new_collection.opts[:paginator] ||= Mongoid::Spacial.paginator

options = self.opts.merge(options)

options[:page] = (page) ? page.to_i : 1

options[:paginator] ||= Mongoid::Spacial.paginator()

options[:per_page] ||= case options[:paginator]
when :will_paginate
@document.per_page
when :kaminari
Kaminari.config.default_per_page
else
Mongoid::Spacial.default_per_page
end

options[:per_page] = options[:per_page].to_i
start = (new_collection.current_page-1)*new_collection.limit_value # assuming current_page is 1 based.

start = (options[:page]-1)*options[:per_page] # assuming current_page is 1 based.

if options[:original]
new_collection.replace(@_original_array[@opts[:skip]+start, options[:per_page]] || [])
if original
@_paginated_array = @_original_array.clone
new_collection.replace(@_original_array[new_collection.opts[:skip]+start, new_collection.limit_value] || [])
else
new_collection.slice!(@opts[:skip]+start, options[:per_page])
@_paginated_array ||= self.to_a
new_collection.replace(@_paginated_array[new_collection.opts[:skip]+start, new_collection.limit_value])
end

new_collection.opts[:page] = options[:page]
new_collection.opts[:paginator] = options[:paginator]
new_collection.opts[:per_page] = options[:per_page]

new_collection
end

Expand All @@ -90,10 +73,9 @@ def per(num)

def reset!
self.replace(@_original_array)
new_collection.opts[:page] = nil
new_collection.opts[:paginator] = nil
new_collection.opts[:per_page] = nil
self
@opts = @_original_opts
@_paginated_array = nil
true
end

def reset
Expand All @@ -107,11 +89,23 @@ def total_entries
end

def current_page
@opts[:page]
page = (@opts[:page]) ? @opts[:page].to_i.abs : 1
(@opts[:page] < 1) ? 1 : page
end

def limit_value
@opts[:per_page]
if @opts[:per_page]
@opts[:per_page] = @opts[:per_page].to_i.abs
else
@opts[:per_page] = case new_collection.opts[:paginator]
when :will_paginate
@document.per_page
when :kaminari
Kaminari.config.default_per_page
else
Mongoid::Spacial.default_per_page
end
end
end
alias_method :per_page, :limit_value

Expand Down
37 changes: 30 additions & 7 deletions spec/functional/mongoid/spacial/geo_near_results_spec.rb
Expand Up @@ -5,29 +5,52 @@
Bar.delete_all
Bar.create_indexes

50.times do
Bar.create({:location => [rand(360)-180,rand(360)-180]})
50.times do |i|
Bar.create(:name => i.to_s, :location => [rand(358)-179,rand(358)-179])
end
end

before(:each) do
while Bar.count < 50
end
end

context ":paginator :array" do
[nil,1,2].each do |page|
let!(:bars) { Bar.geo_near([1,1]) }
let!(:sorted_bars) { Bar.geo_near([1,1]).sort_by {|b| b.name.to_i}}
[nil,1,2].each do |page|
it "page=#{page} should have 25" do
Bar.geo_near([1,1]).page(page).size.should == 25
bars.page(page).size.should == 25
end
end

[1,2].each do |page|
it "modified result should keep order after pagination" do
sorted_bars.page(page).should == sorted_bars.slice((page-1)*25,25)
end
end

{ nil => 25, 20 => 20 , 30 => 20, 50 => 0}.each do |per, total|
it "page=2 per=#{per} should have #{total}" do
bars.per(per).page(2).size.should == total
bars.page(2).per(per).size.should == total
end
end

it "page=3 should have 0" do
Bar.geo_near([1,1]).page(3).size.should == 0
bars.page(3).size.should == 0
end

it "per=5" do
Bar.geo_near([1,1]).per(5).size.should == 5
bars.per(5).size.should == 5
end

it "page=10 per=5" do
bars.per(5).page(10).should == bars[45..50]
end
end

context ":paginator :kaminari" do
context ":paginator :kaminari" do
let!(:near) {Bar.geo_near([1,1]).page(1)}
it "should have current_page" do
near.current_page.should == 1
Expand Down

0 comments on commit c27de4a

Please sign in to comment.