sunspot 2.0.0.pre.120925 → 2.0.0.pre.130115

Sign up to get free protection for your applications and to get access to all the features.
@@ -70,8 +70,6 @@ module Sunspot
70
70
  #
71
71
  # field_name<Symbol>:: the field to use for grouping
72
72
  def group(*field_names, &block)
73
- options = Sunspot::Util.extract_options_from(field_names)
74
-
75
73
  field_names.each do |field_name|
76
74
  field = @setup.field(field_name)
77
75
  group = @query.add_group(Sunspot::Query::FieldGroup.new(field))
@@ -5,8 +5,6 @@ module Sunspot
5
5
  # handler.
6
6
  #
7
7
  class Fulltext
8
- attr_reader :exclude_fields #:nodoc:
9
-
10
8
  # accept function in boost
11
9
  include Functional
12
10
 
data/lib/sunspot/field.rb CHANGED
@@ -12,6 +12,7 @@ module Sunspot
12
12
  @name, @type = name.to_sym, type
13
13
  @stored = !!options.delete(:stored)
14
14
  @more_like_this = !!options.delete(:more_like_this)
15
+ @multiple ||= false
15
16
  set_indexed_name(options)
16
17
  raise ArgumentError, "Field of type #{type} cannot be used for more_like_this" unless type.accepts_more_like_this? or !@more_like_this
17
18
  end
@@ -34,7 +35,7 @@ module Sunspot
34
35
  #
35
36
  def to_indexed(value)
36
37
  if value.is_a? Array
37
- if @multiple
38
+ if multiple?
38
39
  value.map { |val| to_indexed(val) }
39
40
  else
40
41
  raise ArgumentError, "#{name} is not a multiple-value field, so it cannot index values #{value.inspect}"
@@ -106,7 +107,7 @@ module Sunspot
106
107
  if options[:as]
107
108
  options.delete(:as).to_s
108
109
  else
109
- "#{@type.indexed_name(@name).to_s}#{'m' if @multiple }#{'s' if @stored}#{'v' if more_like_this?}"
110
+ "#{@type.indexed_name(@name).to_s}#{'m' if multiple? }#{'s' if @stored}#{'v' if more_like_this?}"
110
111
  end
111
112
  end
112
113
 
@@ -10,6 +10,9 @@ module Sunspot
10
10
  else
11
11
  @scope.add_positive_restriction(TypeField.instance, Restriction::AnyOf, types)
12
12
  end
13
+
14
+ @pagination = nil
15
+ @parameter_adjustment = nil
13
16
  end
14
17
 
15
18
  def solr_parameter_adjustment=(block)
@@ -15,6 +15,12 @@ module Sunspot
15
15
  @boost_queries = []
16
16
  @boost_functions = []
17
17
  @highlights = []
18
+
19
+ @minimum_match = nil
20
+ @phrase_fields = nil
21
+ @phrase_slop = nil
22
+ @query_phrase_slop = nil
23
+ @tie = nil
18
24
  end
19
25
 
20
26
  #
@@ -31,7 +31,7 @@ module Sunspot
31
31
  # to include a tag in the local params.
32
32
  #
33
33
  def tagged?
34
- !!@tag
34
+ defined?(@tag) && !!@tag
35
35
  end
36
36
  end
37
37
  end
@@ -5,6 +5,11 @@ module Sunspot
5
5
  #
6
6
  class FunctionQuery
7
7
  include RSolr::Char
8
+
9
+ def ^(y)
10
+ @boost_amount = y
11
+ self
12
+ end
8
13
  end
9
14
 
10
15
  #
@@ -16,7 +21,7 @@ module Sunspot
16
21
  end
17
22
 
18
23
  def to_s
19
- Type.to_literal(@constant)
24
+ Type.to_literal(@constant) << (@boost_amount ? "^#{@boost_amount}" : "")
20
25
  end
21
26
  end
22
27
 
@@ -29,7 +34,7 @@ module Sunspot
29
34
  end
30
35
 
31
36
  def to_s
32
- "#{escape(@field.indexed_name)}"
37
+ "#{escape(@field.indexed_name)}" << (@boost_amount ? "^#{@boost_amount}" : "")
33
38
  end
34
39
  end
35
40
 
@@ -45,7 +50,7 @@ module Sunspot
45
50
 
46
51
  def to_s
47
52
  params = @function_args.map { |arg| arg.to_s }.join(",")
48
- "#{@function_name}(#{params})"
53
+ "#{@function_name}(#{params})" << (@boost_amount ? "^#{@boost_amount}" : "")
49
54
  end
50
55
  end
51
56
  end
@@ -1,6 +1,6 @@
1
1
  begin
2
2
  require 'geohash'
3
- rescue LoadError => e
3
+ rescue LoadError
4
4
  require 'pr_geohash'
5
5
  end
6
6
 
@@ -1,15 +1,49 @@
1
1
  module Sunspot
2
2
  module Query
3
+
3
4
  class RangeFacet < AbstractFieldFacet
5
+ def initialize(field, options)
6
+ if exclude_filters = options[:exclude]
7
+ @exclude_tag = Util.Array(exclude_filters).map do |filter|
8
+ filter.tag
9
+ end.join(',')
10
+ end
11
+ super
12
+ end
13
+
4
14
  def to_params
5
15
  params = super
6
- params[:"facet.range"] = [@field.indexed_name]
16
+ params[:"facet.range"] = [field_name_with_local_params]
7
17
  params[qualified_param('range.start')] = @field.to_indexed(@options[:range].first)
8
18
  params[qualified_param('range.end')] = @field.to_indexed(@options[:range].last)
9
19
  params[qualified_param('range.gap')] = "#{@options[:range_interval] || 10}"
10
20
  params[qualified_param('range.include')] = @options[:include].to_s if @options[:include]
11
21
  params
12
22
  end
23
+
24
+ private
25
+
26
+ def local_params
27
+ @local_params ||=
28
+ begin
29
+ local_params = {}
30
+ local_params[:ex] = @exclude_tag if @exclude_tag
31
+ local_params[:key] = @options[:name] if @options[:name]
32
+ local_params
33
+ end
34
+ end
35
+
36
+ def field_name_with_local_params
37
+ if local_params.empty?
38
+ @field.indexed_name
39
+ else
40
+ pairs = local_params.map do |key, value|
41
+ "#{key}=#{value}"
42
+ end
43
+ "{!#{pairs.join(' ')}}#{@field.indexed_name}"
44
+ end
45
+ end
13
46
  end
47
+
14
48
  end
15
49
  end
@@ -76,8 +76,18 @@ module Sunspot
76
76
  # (usually) randomly.
77
77
  #
78
78
  class RandomSort < Abstract
79
+ def initialize(options_or_direction=nil)
80
+ if options_or_direction.is_a?(Hash)
81
+ @seed, @direction = options_or_direction[:seed], options_or_direction[:direction]
82
+ else
83
+ @direction = options_or_direction
84
+ end
85
+
86
+ @direction = (@direction || :asc).to_sym
87
+ end
88
+
79
89
  def to_param
80
- "random_#{rand(1<<16)} #{direction_for_solr}"
90
+ "random_#{@seed || rand(1<<6)} #{direction_for_solr}"
81
91
  end
82
92
  end
83
93
 
@@ -1,8 +1,7 @@
1
1
  module Sunspot
2
2
  module Search
3
3
 
4
- class PaginatedCollection
5
- instance_methods.each { |m| undef_method m unless m =~ /^__|instance_eval|object_id/ }
4
+ class PaginatedCollection < Array
6
5
 
7
6
  attr_reader :current_page, :per_page
8
7
  attr_accessor :total_count
@@ -11,10 +10,10 @@ module Sunspot
11
10
  alias :limit_value :per_page
12
11
 
13
12
  def initialize(collection, page, per_page, total)
14
- @collection = collection
15
13
  @current_page = page
16
14
  @per_page = per_page
17
15
  @total_count = total
16
+ replace collection
18
17
  end
19
18
 
20
19
  def total_pages
@@ -45,12 +44,7 @@ module Sunspot
45
44
  def offset
46
45
  (current_page - 1) * per_page
47
46
  end
48
-
49
- private
50
-
51
- def method_missing(method, *args, &block)
52
- @collection.send(method, *args, &block)
53
- end
47
+ alias :offset_value :offset
54
48
 
55
49
  end
56
50
  end
data/lib/sunspot/setup.rb CHANGED
@@ -14,6 +14,7 @@ module Sunspot
14
14
  @stored_field_factories_cache = Hash.new { |h, k| h[k] = [] }
15
15
  @more_like_this_field_factories_cache = Hash.new { |h, k| h[k] = [] }
16
16
  @dsl = DSL::Fields.new(self)
17
+ @document_boost_extractor = nil
17
18
  add_field_factory(:class, Type::ClassType.instance)
18
19
  end
19
20
 
data/lib/sunspot/type.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'singleton'
2
2
  begin
3
3
  require 'geohash'
4
- rescue LoadError => e
4
+ rescue LoadError
5
5
  require 'pr_geohash'
6
6
  end
7
7
 
data/lib/sunspot/util.rb CHANGED
@@ -202,7 +202,7 @@ module Sunspot
202
202
  class <<self
203
203
  def instance_eval_with_context(receiver, &block)
204
204
  calling_context = eval('self', block.binding)
205
- if parent_calling_context = calling_context.instance_eval{@__calling_context__}
205
+ if parent_calling_context = calling_context.instance_eval{@__calling_context__ if defined?(@__calling_context__)}
206
206
  calling_context = parent_calling_context
207
207
  end
208
208
  new(receiver, calling_context).instance_eval(&block)
@@ -1,3 +1,3 @@
1
1
  module Sunspot
2
- VERSION = '2.0.0.pre.120925'
2
+ VERSION = '2.0.0.pre.130115'
3
3
  end
@@ -287,6 +287,17 @@ shared_examples_for "facetable query" do
287
287
  connection.should have_last_search_with(:"f.average_rating_ft.facet.range.gap" => "1")
288
288
  end
289
289
 
290
+ it 'tags and excludes a scope filter in a range facet' do
291
+ search do |query|
292
+ blog_filter = query.with(:blog_id, 1)
293
+ query.facet(:average_rating, :range => @range, :exclude => blog_filter)
294
+ end
295
+ filter_tag = get_filter_tag('blog_id_i:1')
296
+ connection.should have_last_search_with(
297
+ :"facet.range" => %W({!ex=#{filter_tag}}average_rating_ft)
298
+ )
299
+ end
300
+
290
301
  it 'sets the include if one is specified' do
291
302
  search do |query|
292
303
  query.facet :average_rating, :range => @range, :include => :edge
@@ -10,6 +10,15 @@ describe 'function query' do
10
10
  connection.should have_last_search_including(:bf, 'average_rating_ft')
11
11
  end
12
12
 
13
+ it "should send query to solr with boost function and boost amount" do
14
+ session.search Post do
15
+ keywords('pizza') do
16
+ boost(function { :average_rating }^5)
17
+ end
18
+ end
19
+ connection.should have_last_search_including(:bf, 'average_rating_ft^5')
20
+ end
21
+
13
22
  it "should handle boost function with constant float" do
14
23
  session.search Post do
15
24
  keywords('pizza') do
@@ -19,6 +28,15 @@ describe 'function query' do
19
28
  connection.should have_last_search_including(:bf, '10.5')
20
29
  end
21
30
 
31
+ it "should handle boost function with constant float and boost amount" do
32
+ session.search Post do
33
+ keywords('pizza') do
34
+ boost(function { 10.5 }^5)
35
+ end
36
+ end
37
+ connection.should have_last_search_including(:bf, '10.5^5')
38
+ end
39
+
22
40
  it "should handle boost function with time literal" do
23
41
  session.search Post do
24
42
  keywords('pizza') do
@@ -45,6 +63,15 @@ describe 'function query' do
45
63
  end
46
64
  connection.should have_last_search_including(:bf, 'sub(average_rating_ft,10)')
47
65
  end
66
+
67
+ it "should handle boost amounts on function query block" do
68
+ session.search Post do
69
+ keywords('pizza') do
70
+ boost(function { sub(:average_rating, 10)^5 })
71
+ end
72
+ end
73
+ connection.should have_last_search_including(:bf, 'sub(average_rating_ft,10)^5')
74
+ end
48
75
 
49
76
  it "should handle nested functions in a function query block" do
50
77
  session.search Post do
@@ -68,6 +68,27 @@ shared_examples_for 'sortable query' do
68
68
  connection.searches.last[:sort].should =~ /^random_\d+ asc$/
69
69
  end
70
70
 
71
+ it 'orders by random with declared direction' do
72
+ search do
73
+ order_by :random, :desc
74
+ end
75
+ connection.searches.last[:sort].should =~ /^random_\d+ desc$/
76
+ end
77
+
78
+ it 'orders by random with provided seed value' do
79
+ search do
80
+ order_by :random, :seed => 9001
81
+ end
82
+ connection.searches.last[:sort].should =~ /^random_9001 asc$/
83
+ end
84
+
85
+ it 'orders by random with provided seed value and direction' do
86
+ search do
87
+ order_by :random, :seed => 12345, :direction => :desc
88
+ end
89
+ connection.searches.last[:sort].should =~ /^random_12345 desc$/
90
+ end
91
+
71
92
  it 'orders by score' do
72
93
  search do
73
94
  order_by :score, :desc
@@ -5,6 +5,18 @@ describe "PaginatedCollection" do
5
5
 
6
6
  it { subject.should be_an(Array) }
7
7
 
8
+ describe "#send" do
9
+ it 'should allow send' do
10
+ expect { subject.send(:current_page) }.not_to raise_error(NoMethodError)
11
+ end
12
+ end
13
+
14
+ describe "#respond_to?" do
15
+ it 'should return true for current_page' do
16
+ subject.respond_to?(:current_page).should be_true
17
+ end
18
+ end
19
+
8
20
  context "behaves like a WillPaginate::Collection" do
9
21
  it { subject.total_entries.should eql(20) }
10
22
  it { subject.total_pages.should eql(2) }
@@ -372,9 +372,12 @@ describe 'scoped_search' do
372
372
  end
373
373
 
374
374
  describe 'ordering by random' do
375
- it 'should order randomly (run this test again if it fails)' do
375
+ before do
376
376
  Sunspot.remove_all
377
377
  Sunspot.index!(Array.new(100) { Post.new })
378
+ end
379
+
380
+ it 'should order randomly (run this test again if it fails)' do
378
381
  result_sets = Array.new(2) do
379
382
  Sunspot.search(Post) { order_by_random }.results.map do |result|
380
383
  result.id
@@ -382,5 +385,38 @@ describe 'scoped_search' do
382
385
  end
383
386
  result_sets[0].should_not == result_sets[1]
384
387
  end
388
+
389
+ # This could fail if the random set returned just happens to be the same as the last random set (the nature of randomness)
390
+ it 'should order randomly using the order_by function and passing a direction' do
391
+ result_sets = Array.new(2) do
392
+ Sunspot.search(Post) { order_by(:random, :desc) }.results.map do |result|
393
+ result.id
394
+ end
395
+ end
396
+ result_sets[0].should_not == result_sets[1]
397
+ end
398
+
399
+ context 'when providing a custom seed value' do
400
+ before do
401
+ @first_results = Sunspot.search(Post) do
402
+ order_by(:random, :seed => 12345)
403
+ end.results.map { |result| result.id }
404
+ end
405
+
406
+ # This could fail if the random set returned just happens to be the same as the last random set (the nature of randomness)
407
+ it 'should return different results when passing a different seed value' do
408
+ next_results = Sunspot.search(Post) do
409
+ order_by(:random, :seed => 54321)
410
+ end.results.map { |result| result.id }
411
+ next_results.should_not == @first_results
412
+ end
413
+
414
+ it 'should return the same results when passing the same seed value' do
415
+ next_results = Sunspot.search(Post) do
416
+ order_by(:random, :seed => 12345)
417
+ end.results.map { |result| result.id }
418
+ next_results.should == @first_results
419
+ end
420
+ end
385
421
  end
386
422
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sunspot
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.pre.120925
4
+ version: 2.0.0.pre.130115
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -27,52 +27,72 @@ authors:
27
27
  autorequire:
28
28
  bindir: bin
29
29
  cert_chain: []
30
- date: 2012-09-25 00:00:00.000000000 Z
30
+ date: 2013-01-15 00:00:00.000000000 Z
31
31
  dependencies:
32
32
  - !ruby/object:Gem::Dependency
33
33
  name: rsolr
34
- requirement: &70302521090680 !ruby/object:Gem::Requirement
35
- none: false
34
+ prerelease: false
35
+ requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - ~>
38
38
  - !ruby/object:Gem::Version
39
39
  version: 1.0.7
40
+ none: false
40
41
  type: :runtime
41
- prerelease: false
42
- version_requirements: *70302521090680
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: 1.0.7
47
+ none: false
43
48
  - !ruby/object:Gem::Dependency
44
49
  name: pr_geohash
45
- requirement: &70302521089300 !ruby/object:Gem::Requirement
46
- none: false
50
+ prerelease: false
51
+ requirement: !ruby/object:Gem::Requirement
47
52
  requirements:
48
53
  - - ~>
49
54
  - !ruby/object:Gem::Version
50
55
  version: '1.0'
56
+ none: false
51
57
  type: :runtime
52
- prerelease: false
53
- version_requirements: *70302521089300
58
+ version_requirements: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ~>
61
+ - !ruby/object:Gem::Version
62
+ version: '1.0'
63
+ none: false
54
64
  - !ruby/object:Gem::Dependency
55
65
  name: rspec
56
- requirement: &70302521088380 !ruby/object:Gem::Requirement
57
- none: false
66
+ prerelease: false
67
+ requirement: !ruby/object:Gem::Requirement
58
68
  requirements:
59
69
  - - ~>
60
70
  - !ruby/object:Gem::Version
61
71
  version: 2.6.0
72
+ none: false
62
73
  type: :development
63
- prerelease: false
64
- version_requirements: *70302521088380
74
+ version_requirements: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ~>
77
+ - !ruby/object:Gem::Version
78
+ version: 2.6.0
79
+ none: false
65
80
  - !ruby/object:Gem::Dependency
66
81
  name: hanna
67
- requirement: &70302521086620 !ruby/object:Gem::Requirement
68
- none: false
82
+ prerelease: false
83
+ requirement: !ruby/object:Gem::Requirement
69
84
  requirements:
70
85
  - - ! '>='
71
86
  - !ruby/object:Gem::Version
72
87
  version: '0'
88
+ none: false
73
89
  type: :development
74
- prerelease: false
75
- version_requirements: *70302521086620
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ none: false
76
96
  description: ! " Sunspot is a library providing a powerful, all-ruby API for the
77
97
  Solr search engine. Sunspot manages the configuration of persistent\n Ruby classes
78
98
  for search and indexing and exposes Solr's most powerful features through a collection
@@ -276,20 +296,20 @@ rdoc_options:
276
296
  require_paths:
277
297
  - lib
278
298
  required_ruby_version: !ruby/object:Gem::Requirement
279
- none: false
280
299
  requirements:
281
300
  - - ! '>='
282
301
  - !ruby/object:Gem::Version
283
302
  version: '0'
284
- required_rubygems_version: !ruby/object:Gem::Requirement
285
303
  none: false
304
+ required_rubygems_version: !ruby/object:Gem::Requirement
286
305
  requirements:
287
306
  - - ! '>'
288
307
  - !ruby/object:Gem::Version
289
308
  version: 1.3.1
309
+ none: false
290
310
  requirements: []
291
311
  rubyforge_project: sunspot
292
- rubygems_version: 1.8.15
312
+ rubygems_version: 1.8.24
293
313
  signing_key:
294
314
  specification_version: 3
295
315
  summary: Library for expressive, powerful interaction with the Solr search engine