sunspot 1.0.5 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. data/README.rdoc +3 -0
  2. data/TODO +6 -5
  3. data/bin/sunspot-solr +4 -0
  4. data/installer/config/schema.yml +24 -0
  5. data/lib/sunspot/composite_setup.rb +14 -0
  6. data/lib/sunspot/dsl/adjustable.rb +47 -0
  7. data/lib/sunspot/dsl/fulltext.rb +23 -8
  8. data/lib/sunspot/dsl/function.rb +14 -0
  9. data/lib/sunspot/dsl/functional.rb +41 -0
  10. data/lib/sunspot/dsl/more_like_this_query.rb +56 -0
  11. data/lib/sunspot/dsl/paginatable.rb +28 -0
  12. data/lib/sunspot/dsl/search.rb +1 -1
  13. data/lib/sunspot/dsl/{query.rb → standard_query.rb} +4 -49
  14. data/lib/sunspot/dsl.rb +3 -2
  15. data/lib/sunspot/field.rb +16 -2
  16. data/lib/sunspot/indexer.rb +1 -1
  17. data/lib/sunspot/installer/schema_builder.rb +1 -1
  18. data/lib/sunspot/installer/solrconfig_updater.rb +13 -0
  19. data/lib/sunspot/installer/task_helper.rb +1 -1
  20. data/lib/sunspot/query/abstract_field_facet.rb +5 -0
  21. data/lib/sunspot/query/boost_query.rb +5 -1
  22. data/lib/sunspot/query/{query.rb → common_query.rb} +26 -20
  23. data/lib/sunspot/query/composite_fulltext.rb +31 -0
  24. data/lib/sunspot/query/dismax.rb +45 -6
  25. data/lib/sunspot/query/function_query.rb +52 -0
  26. data/lib/sunspot/query/more_like_this.rb +60 -0
  27. data/lib/sunspot/query/more_like_this_query.rb +12 -0
  28. data/lib/sunspot/query/standard_query.rb +20 -0
  29. data/lib/sunspot/query/text_field_boost.rb +2 -0
  30. data/lib/sunspot/query.rb +3 -2
  31. data/lib/sunspot/search/abstract_search.rb +302 -0
  32. data/lib/sunspot/search/date_facet.rb +1 -1
  33. data/lib/sunspot/search/facet_row.rb +1 -1
  34. data/lib/sunspot/search/field_facet.rb +1 -1
  35. data/lib/sunspot/search/highlight.rb +1 -1
  36. data/lib/sunspot/search/hit.rb +1 -1
  37. data/lib/sunspot/search/more_like_this_search.rb +31 -0
  38. data/lib/sunspot/search/query_facet.rb +1 -1
  39. data/lib/sunspot/search/standard_search.rb +21 -0
  40. data/lib/sunspot/search.rb +3 -288
  41. data/lib/sunspot/server.rb +8 -4
  42. data/lib/sunspot/session.rb +30 -2
  43. data/lib/sunspot/session_proxy/master_slave_session_proxy.rb +1 -1
  44. data/lib/sunspot/session_proxy/sharding_session_proxy.rb +9 -0
  45. data/lib/sunspot/session_proxy/thread_local_session_proxy.rb +9 -2
  46. data/lib/sunspot/setup.rb +32 -3
  47. data/lib/sunspot/type.rb +74 -0
  48. data/lib/sunspot/util.rb +3 -2
  49. data/lib/sunspot/version.rb +1 -1
  50. data/lib/sunspot.rb +9 -1
  51. data/solr/solr/conf/schema.xml +12 -0
  52. data/solr/solr/conf/solrconfig.xml +6 -0
  53. data/spec/api/indexer/attributes_spec.rb +9 -3
  54. data/spec/api/indexer/fulltext_spec.rb +2 -2
  55. data/spec/api/indexer/removal_spec.rb +1 -1
  56. data/spec/api/query/advanced_manipulation_examples.rb +35 -0
  57. data/spec/api/query/{connectives_spec.rb → connectives_examples.rb} +19 -19
  58. data/spec/api/query/{dynamic_fields_spec.rb → dynamic_fields_examples.rb} +33 -17
  59. data/spec/api/query/{faceting_spec.rb → faceting_examples.rb} +146 -43
  60. data/spec/api/query/{fulltext_spec.rb → fulltext_examples.rb} +81 -47
  61. data/spec/api/query/function_spec.rb +70 -0
  62. data/spec/api/query/{highlighting_spec.rb → highlighting_examples.rb} +27 -27
  63. data/spec/api/query/{local_spec.rb → local_examples.rb} +5 -5
  64. data/spec/api/query/more_like_this_spec.rb +140 -0
  65. data/spec/api/query/{ordering_pagination_spec.rb → ordering_pagination_examples.rb} +16 -16
  66. data/spec/api/query/{scope_spec.rb → scope_examples.rb} +44 -61
  67. data/spec/api/query/standard_spec.rb +28 -0
  68. data/spec/api/query/{text_field_scoping_spec.rb → text_field_scoping_examples.rb} +5 -5
  69. data/spec/api/search/dynamic_fields_spec.rb +6 -0
  70. data/spec/api/search/faceting_spec.rb +10 -10
  71. data/spec/api/search/hits_spec.rb +1 -1
  72. data/spec/api/search/results_spec.rb +10 -0
  73. data/spec/api/server_spec.rb +6 -0
  74. data/spec/api/session_proxy/master_slave_session_proxy_spec.rb +2 -2
  75. data/spec/api/session_proxy/thread_local_session_proxy_spec.rb +17 -0
  76. data/spec/api/spec_helper.rb +2 -0
  77. data/spec/helpers/query_helper.rb +25 -0
  78. data/spec/helpers/search_helper.rb +4 -0
  79. data/spec/integration/faceting_spec.rb +8 -0
  80. data/spec/integration/keyword_search_spec.rb +75 -3
  81. data/spec/integration/local_search_spec.rb +1 -1
  82. data/spec/integration/more_like_this_spec.rb +43 -0
  83. data/spec/mocks/comment.rb +1 -1
  84. data/spec/mocks/connection.rb +27 -12
  85. data/spec/mocks/post.rb +5 -4
  86. data/spec/spec_helper.rb +4 -21
  87. data/tasks/gemspec.rake +1 -1
  88. metadata +39 -27
  89. data/spec/api/query/adjust_params_spec.rb +0 -37
  90. data/spec/api/query/facet_local_params_spec.rb +0 -103
@@ -53,7 +53,7 @@ describe 'faceting', :type => :search do
53
53
  end
54
54
 
55
55
  it 'returns float facet' do
56
- stub_facet(:average_rating_f, '9.3' => 2, '1.1' => 1)
56
+ stub_facet(:average_rating_ft, '9.3' => 2, '1.1' => 1)
57
57
  result = session.search Post do
58
58
  facet :average_rating
59
59
  end
@@ -62,7 +62,7 @@ describe 'faceting', :type => :search do
62
62
 
63
63
  it 'returns time facet' do
64
64
  stub_facet(
65
- :published_at_d,
65
+ :published_at_dt,
66
66
  '2009-04-07T20:25:23Z' => 3,
67
67
  '2009-04-07T20:26:19Z' => 2,
68
68
  '2050-04-07T20:27:15Z' => 1
@@ -181,7 +181,7 @@ describe 'faceting', :type => :search do
181
181
  end
182
182
 
183
183
  it 'returns date range facet' do
184
- stub_date_facet(:published_at_d, 60*60*24, '2009-07-08T04:00:00Z' => 2, '2009-07-07T04:00:00Z' => 1)
184
+ stub_date_facet(:published_at_dt, 60*60*24, '2009-07-08T04:00:00Z' => 2, '2009-07-07T04:00:00Z' => 1)
185
185
  start_time = Time.utc(2009, 7, 7, 4)
186
186
  end_time = start_time + 2*24*60*60
187
187
  result = session.search(Post) { facet(:published_at, :time_range => start_time..end_time) }
@@ -191,7 +191,7 @@ describe 'faceting', :type => :search do
191
191
  end
192
192
 
193
193
  it 'returns date range facet sorted by count' do
194
- stub_date_facet(:published_at_d, 60*60*24, '2009-07-08T04:00:00Z' => 2, '2009-07-07T04:00:00Z' => 1)
194
+ stub_date_facet(:published_at_dt, 60*60*24, '2009-07-08T04:00:00Z' => 2, '2009-07-07T04:00:00Z' => 1)
195
195
  start_time = Time.utc(2009, 7, 7, 4)
196
196
  end_time = start_time + 2*24*60*60
197
197
  result = session.search(Post) { facet(:published_at, :time_range => start_time..end_time, :sort => :count) }
@@ -202,8 +202,8 @@ describe 'faceting', :type => :search do
202
202
 
203
203
  it 'returns query facet' do
204
204
  stub_query_facet(
205
- 'average_rating_f:[3\.0 TO 5\.0]' => 3,
206
- 'average_rating_f:[1\.0 TO 3\.0]' => 1
205
+ 'average_rating_ft:[3\.0 TO 5\.0]' => 3,
206
+ 'average_rating_ft:[1\.0 TO 3\.0]' => 1
207
207
  )
208
208
  search = session.search(Post) do
209
209
  facet :average_rating do
@@ -236,10 +236,10 @@ describe 'faceting', :type => :search do
236
236
 
237
237
  before :each do
238
238
  stub_query_facet(
239
- 'average_rating_f:[1\.0 TO 2\.0]' => 2,
240
- 'average_rating_f:[2\.0 TO 3\.0]' => 3,
241
- 'average_rating_f:[3\.0 TO 4\.0]' => 1,
242
- 'average_rating_f:[4\.0 TO 5\.0]' => 0
239
+ 'average_rating_ft:[1\.0 TO 2\.0]' => 2,
240
+ 'average_rating_ft:[2\.0 TO 3\.0]' => 3,
241
+ 'average_rating_ft:[3\.0 TO 4\.0]' => 1,
242
+ 'average_rating_ft:[4\.0 TO 5\.0]' => 0
243
243
  )
244
244
  end
245
245
 
@@ -107,7 +107,7 @@ describe 'hits', :type => :search do
107
107
  end
108
108
 
109
109
  it 'should return stored text fields' do
110
- stub_full_results('instance' => Post.new, 'body_texts' => 'Body')
110
+ stub_full_results('instance' => Post.new, 'body_textsv' => 'Body')
111
111
  session.search(Post, Namespaced::Comment).hits.first.stored(:body).should == 'Body'
112
112
  end
113
113
 
@@ -25,6 +25,11 @@ describe 'search results', :type => :search do
25
25
  session.search(Post, Namespaced::Comment).results.should == results
26
26
  end
27
27
 
28
+ it 'gracefully returns empty results when response is nil' do
29
+ stub_nil_results
30
+ session.search(Post).results.should == []
31
+ end
32
+
28
33
  if ENV['USE_WILL_PAGINATE']
29
34
 
30
35
  it 'returns search total as attribute of results' do
@@ -50,6 +55,11 @@ describe 'search results', :type => :search do
50
55
  session.search(Post) { paginate(:page => 1) }.total.should == 4
51
56
  end
52
57
 
58
+ it 'returns total for nil search' do
59
+ stub_nil_results
60
+ session.search(Post).total.should == 0
61
+ end
62
+
53
63
  it 'returns available results if some results are not available from data store' do
54
64
  posts = [Post.new, Post.new]
55
65
  posts.last.destroy
@@ -46,6 +46,12 @@ describe Sunspot::Server do
46
46
  @server.run
47
47
  end
48
48
 
49
+ it 'runs Solr with specified Solr jar' do
50
+ @server.solr_jar = SUNSPOT_START_JAR
51
+ FileUtils.should_receive(:cd).with(File.dirname(SUNSPOT_START_JAR))
52
+ @server.run
53
+ end
54
+
49
55
  describe 'with logging' do
50
56
  before :each do
51
57
  @server.log_level = 'info'
@@ -7,8 +7,8 @@ describe Sunspot::SessionProxy::MasterSlaveSessionProxy do
7
7
  end
8
8
 
9
9
  {
10
- :master_session => Sunspot::Session.public_instance_methods(false) - [:search, 'search', :new_search, 'new_search', :config, 'config'],
11
- :slave_session => [:search, :new_search]
10
+ :master_session => Sunspot::Session.public_instance_methods(false) - [:search, 'search', :new_search, 'new_search', :more_like_this, 'more_like_this', :new_more_like_this, 'new_more_like_this', :config, 'config'],
11
+ :slave_session => [:search, :new_search, :more_like_this, :new_more_like_this]
12
12
  }.each_pair do |delegate, methods|
13
13
  methods.each do |method|
14
14
  it "should delegate #{method} to #{delegate}" do
@@ -1,4 +1,5 @@
1
1
  require File.join(File.dirname(__FILE__), 'spec_helper')
2
+ require 'weakref'
2
3
 
3
4
  describe Sunspot::SessionProxy::ThreadLocalSessionProxy do
4
5
  before :each do
@@ -19,6 +20,22 @@ describe Sunspot::SessionProxy::ThreadLocalSessionProxy do
19
20
  session1.should_not eql(session2)
20
21
  end
21
22
 
23
+ it 'should not have the same session for the same thread in different proxy instances' do
24
+ proxy2 = Sunspot::SessionProxy::ThreadLocalSessionProxy.new(@config)
25
+ @proxy.session.should_not eql(proxy2.session)
26
+ end
27
+
28
+ it 'should garbage collect session instance when proxy dereferenced' do
29
+ ref = WeakRef.new(@proxy.session)
30
+ @proxy = nil
31
+ GC.start
32
+ # need to do this a second time since the reference to the session is
33
+ # destroyed in the finalizer during the first GC run, and thus isn't picked
34
+ # up by that run.
35
+ GC.start
36
+ lambda { ref.inspect }.should raise_error(WeakRef::RefError)
37
+ end
38
+
22
39
  (Sunspot::Session.public_instance_methods(false) - ['config', :config]).each do |method|
23
40
  it "should delegate #{method.inspect} to its session" do
24
41
  args = Array.new(Sunspot::Session.instance_method(method).arity.abs) do
@@ -1 +1,3 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ Dir.glob(File.join(File.dirname(__FILE__), '**', '*_examples.rb')).each { |shared| require(shared) }
@@ -10,4 +10,29 @@ module QueryHelper
10
10
  def session
11
11
  @session ||= Sunspot::Session.new(config, connection)
12
12
  end
13
+
14
+ def get_filter_tag(boolean_query)
15
+ connection.searches.last[:fq].each do |fq|
16
+ if match = fq.match(/^\{!tag=(.+)\}#{Regexp.escape(boolean_query)}$/)
17
+ return match[1]
18
+ end
19
+ end
20
+ nil
21
+ end
22
+
23
+ def subqueries(param)
24
+ q = connection.searches.last[:q]
25
+ subqueries = []
26
+ subqueries = q.scan(%r(_query_:"\{!dismax (.*?)\}(.*?)"))
27
+ subqueries.map do |subquery|
28
+ params = {}
29
+ subquery[0].scan(%r((\S+?)='(.+?)')) do |key, value|
30
+ params[key.to_sym] = value
31
+ end
32
+ unless subquery[1].empty?
33
+ params[:v] = subquery[1]
34
+ end
35
+ params
36
+ end
37
+ end
13
38
  end
@@ -1,4 +1,8 @@
1
1
  module SearchHelper
2
+ def stub_nil_results
3
+ connection.response = { 'response' => nil }
4
+ end
5
+
2
6
  def stub_full_results(*results)
3
7
  count =
4
8
  if results.last.is_a?(Integer) then results.pop
@@ -109,6 +109,14 @@ describe 'search faceting' do
109
109
  search.facet(:title).rows.map { |row| row.value }.should == %w(four three two one)
110
110
  end
111
111
 
112
+ it 'should limit facet values by prefix' do
113
+ search = Sunspot.search(Post) do
114
+ with :blog_id, 1
115
+ facet :title, :prefix => 't'
116
+ end
117
+ search.facet(:title).rows.map { |row| row.value }.sort.should == %w(three two)
118
+ end
119
+
112
120
  it 'should return :all facet' do
113
121
  search = Sunspot.search(Post) do
114
122
  with :blog_id, 1
@@ -10,7 +10,7 @@ describe 'keyword search' do
10
10
  @posts << Post.new(:title => 'A nail abbreviates the recovering insight outside the moron',
11
11
  :body => 'The interpreted strain scans the buffer around the upper temper')
12
12
  @posts << Post.new(:title => 'The toast abbreviates the recovering spirit',
13
- :body => 'Does the wind interpret the buffer, moron?')
13
+ :body => 'Does the host\'s wind interpret the buffer, moron?')
14
14
  Sunspot.index!(*@posts)
15
15
  @comment = Namespaced::Comment.new(:body => 'Hey there where ya goin, not exactly knowin, who says you have to call just one place toast.')
16
16
  Sunspot.index!(@comment)
@@ -47,6 +47,45 @@ describe 'keyword search' do
47
47
  end.results
48
48
  results.should == [@posts[1]]
49
49
  end
50
+
51
+ it 'matches multiple keywords on different fields using subqueries' do
52
+ search = Sunspot.search(Post) do
53
+ keywords 'moron', :fields => [:title]
54
+ keywords 'wind', :fields => [:body]
55
+ end
56
+ search.results.should == []
57
+
58
+ search = Sunspot.search(Post) do
59
+ keywords 'moron', :fields => [:title]
60
+ keywords 'buffer', :fields => [:body]
61
+ end
62
+ search.results.should == [@posts[1]]
63
+ end
64
+
65
+ it 'matches multiple keywords with escaped characters' do
66
+ search = Sunspot.search(Post) do
67
+ keywords 'spirit', :fields => [:title]
68
+ keywords 'host\'s', :fields => [:body]
69
+ end
70
+ search.results.should == [@posts[2]]
71
+ end
72
+
73
+ it 'matches multiple keywords with phrase-based search' do
74
+ search = Sunspot.search(Post) do
75
+ keywords 'spirit', :fields => [:title]
76
+ keywords '"interpret the buffer"', :fields => [:body]
77
+ keywords '"does the"', :fields => [:body]
78
+ end
79
+ search.results.should == [@posts[2]]
80
+ end
81
+
82
+ it 'matches multiple keywords different options' do
83
+ search = Sunspot.search(Post) do
84
+ keywords 'insufficient nonexistent', :fields => [:title], :minimum_match => 1
85
+ keywords 'wind does', :fields => [:body], :minimum_match => 2
86
+ end
87
+ search.results.should == [@posts[0]]
88
+ end
50
89
  end
51
90
 
52
91
  describe 'with field boost' do
@@ -75,7 +114,7 @@ describe 'keyword search' do
75
114
 
76
115
  it 'should assign a higher score to the higher-boosted document' do
77
116
  search = Sunspot.search(Post) { keywords 'test' }
78
- search.hits.map { |hit| hit.primary_key }.should ==
117
+ search.hits.map { |hit| hit.primary_key }.should ==
79
118
  @posts.map { |post| post.id.to_s }
80
119
  search.hits.first.score.should > search.hits.last.score
81
120
  end
@@ -110,7 +149,7 @@ describe 'keyword search' do
110
149
  hits.first.instance.should == @comments.first
111
150
  hits.first.score.should > hits.last.score
112
151
  end
113
-
152
+
114
153
  it 'assigns a higher score to documents in which the search terms appear in a higher boosted phrase field' do
115
154
  hits = Sunspot.search(Namespaced::Comment) do
116
155
  keywords 'test text' do
@@ -242,4 +281,37 @@ describe 'keyword search' do
242
281
  @sorted_hits[4].score.should == @sorted_hits[5].score
243
282
  end
244
283
  end
284
+
285
+ describe 'with function queries' do
286
+ before :each do
287
+ Sunspot.remove_all
288
+ end
289
+
290
+ after :each do
291
+ @search.results.should == @posts
292
+ @search.hits.first.score.should > @search.hits.last.score
293
+ end
294
+
295
+ it 'boosts via function query with float' do
296
+ @posts = [Post.new(:title => 'test', :ratings_average => 4.0),
297
+ Post.new(:title => 'test', :ratings_average => 2.0)]
298
+ Sunspot.index!(@posts)
299
+ @search = Sunspot.search(Post) do
300
+ keywords('test') do
301
+ boost function { :average_rating }
302
+ end
303
+ end
304
+ end
305
+
306
+ it 'boosts via function query with date' do
307
+ @posts = [Post.new(:title => 'test', :published_at => Time.now),
308
+ Post.new(:title => 'test', :published_at => Time.now - 60*60*24*31*6)] # roughly six months ago
309
+ Sunspot.index!(@posts)
310
+ @search = Sunspot.search(Post) do
311
+ keywords('test') do
312
+ boost function { recip(ms(Time.now, :published_at), 3.16e-11, 1, 1) }
313
+ end
314
+ end
315
+ end
316
+ end
245
317
  end
@@ -55,7 +55,7 @@ describe 'local search' do
55
55
  end
56
56
  search.results.should == [@posts[1], @posts[4]]
57
57
  end
58
-
58
+
59
59
  it 'should order by arbitrary field' do
60
60
  search = Sunspot.search(Post) do |query|
61
61
  query.near(ORIGIN, :distance => 20)
@@ -0,0 +1,43 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe 'more_like_this' do
4
+ before :all do
5
+ Sunspot.remove_all
6
+ @posts = [
7
+ Post.new(:body => "one two three", :tags => %w(ruby sunspot rsolr)),
8
+ Post.new(:body => "four five six", :tags => %w(ruby solr lucene)),
9
+ Post.new(:body => "two three four", :tags => %w(python sqlalchemy)),
10
+ Post.new(:body => "three four five", :tags => %w(ruby sunspot mat)),
11
+ Post.new(:body => "six seven eight", :tags => %w(bogus airplane))
12
+ ]
13
+ Sunspot.index!(@posts)
14
+ end
15
+
16
+ it 'should return results for all MLT fields' do
17
+ Sunspot.more_like_this(@posts.first).results.to_set.should == @posts[1..3].to_set
18
+ end
19
+
20
+ it 'should return results for specified text field' do
21
+ Sunspot.more_like_this(@posts.first) do
22
+ fields :body
23
+ end.results.to_set.should == @posts[2..3].to_set
24
+ end
25
+
26
+ it 'should return empty result set if no results' do
27
+ Sunspot.more_like_this(@posts.last) do
28
+ with(:title, 'bogus')
29
+ end.results.should == []
30
+ end
31
+
32
+ describe 'when non-indexed object searched' do
33
+ before(:each) { @mlt = Sunspot.more_like_this(Post.new) }
34
+
35
+ it 'should return empty result set' do
36
+ @mlt.results.should == []
37
+ end
38
+
39
+ it 'shoult return a total of 0' do
40
+ @mlt.total.should == 0
41
+ end
42
+ end
43
+ end
@@ -13,7 +13,7 @@ end
13
13
  Sunspot.setup(Namespaced::Comment) do
14
14
  text :body, :author_name
15
15
  string :author_name
16
- time :published_at
16
+ time :published_at, :trie => true
17
17
  long :hash
18
18
  double :average_rating
19
19
  dynamic_float :custom_float, :multiple => true
@@ -24,11 +24,14 @@ module Mock
24
24
  class Connection
25
25
  attr_reader :adds, :commits, :searches, :message, :opts, :deletes_by_query
26
26
  attr_accessor :response
27
+ attr_writer :expected_handler
28
+ undef_method :select # annoyingly defined on Object
27
29
 
28
30
  def initialize(opts = {})
29
31
  @opts = opts
30
32
  @message = OpenStruct.new
31
33
  @adds, @deletes, @deletes_by_query, @commits, @searches = Array.new(5) { [] }
34
+ @expected_handler = :select
32
35
  end
33
36
 
34
37
  def add(documents)
@@ -47,11 +50,18 @@ module Mock
47
50
  @commits << Time.now
48
51
  end
49
52
 
50
- def select(request)
51
- @searches << @last_search = request
53
+ def request(path, params)
54
+ unless path == "/#{@expected_handler}"
55
+ raise ArgumentError, "Expected request to #{@expected_handler} request handler"
56
+ end
57
+ @searches << @last_search = params
52
58
  @response || {}
53
59
  end
54
60
 
61
+ def method_missing(method, *args, &block)
62
+ request("/#{method}", *args)
63
+ end
64
+
55
65
  def has_add_with?(*documents)
56
66
  @adds.any? do |add|
57
67
  documents.all? do |document|
@@ -81,16 +91,7 @@ module Mock
81
91
  end
82
92
 
83
93
  def has_last_search_with?(params)
84
- return unless @last_search
85
- if params.respond_to?(:all?)
86
- params.all? do |key, value|
87
- if @last_search.has_key?(key)
88
- @last_search[key] == value
89
- end
90
- end
91
- else
92
- @last_search.has_key?(params)
93
- end
94
+ with?(@last_search, params) if @last_search
94
95
  end
95
96
 
96
97
  def has_last_search_including?(key, *values)
@@ -103,5 +104,19 @@ module Mock
103
104
  end
104
105
  end
105
106
  end
107
+
108
+ private
109
+
110
+ def with?(request, params)
111
+ if params.respond_to?(:all?)
112
+ params.all? do |key, value|
113
+ if request.has_key?(key)
114
+ request[key] == value
115
+ end
116
+ end
117
+ else
118
+ request.has_key?(params)
119
+ end
120
+ end
106
121
  end
107
122
  end
data/spec/mocks/post.rb CHANGED
@@ -3,7 +3,7 @@ require File.join(File.dirname(__FILE__), 'super_class')
3
3
 
4
4
  class Post < SuperClass
5
5
  attr_accessor :title, :body, :blog_id, :published_at, :ratings_average,
6
- :author_name, :featured, :expire_date, :coordinates
6
+ :author_name, :featured, :expire_date, :coordinates, :tags
7
7
  alias_method :featured?, :featured
8
8
 
9
9
  def category_ids
@@ -32,15 +32,16 @@ end
32
32
 
33
33
  Sunspot.setup(Post) do
34
34
  text :title, :boost => 2
35
- text :body, :stored => true
35
+ text :body, :stored => true, :more_like_this => true
36
36
  text :backwards_title do
37
37
  title.reverse if title
38
38
  end
39
+ text :tags, :more_like_this => true
39
40
  string :title, :stored => true
40
41
  integer :blog_id, :references => Blog
41
42
  integer :category_ids, :multiple => true
42
- float :average_rating, :using => :ratings_average
43
- time :published_at
43
+ float :average_rating, :using => :ratings_average, :trie => true
44
+ time :published_at, :trie => true
44
45
  date :expire_date
45
46
  boolean :featured, :using => :featured?
46
47
  string :sort_title do
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,3 @@
1
- using_gems = false
2
-
3
1
  if rsolr_gem_version = ENV['RSOLR_GEM_VERSION']
4
2
  STDERR.puts("Forcing rsolr gem version #{rsolr_gem_version}")
5
3
  using_gems = true
@@ -7,35 +5,20 @@ if rsolr_gem_version = ENV['RSOLR_GEM_VERSION']
7
5
  gem 'rsolr', rsolr_gem_version
8
6
  end
9
7
 
8
+ require 'ostruct'
10
9
  begin
11
10
  require 'spec'
12
- begin
13
- require 'ruby-debug'
14
- rescue LoadError => e
15
- if using_gems
16
- module Kernel
17
- def debugger
18
- STDERR.puts('Debugger is not available')
19
- end
20
- end
21
- else
22
- raise(e)
23
- end
24
- end
25
11
  if ENV['USE_WILL_PAGINATE']
26
12
  require 'will_paginate'
27
13
  require 'will_paginate/collection'
28
14
  end
29
15
  rescue LoadError => e
30
- require 'rubygems'
31
- if using_gems
32
- raise(e)
33
- else
34
- using_gems = true
16
+ if require 'rubygems'
35
17
  retry
18
+ else
19
+ raise(e)
36
20
  end
37
21
  end
38
- require 'ostruct'
39
22
 
40
23
  unless gem_name = ENV['SUNSPOT_TEST_GEM']
41
24
  $:.unshift(File.dirname(__FILE__) + '/../lib')
data/tasks/gemspec.rake CHANGED
@@ -10,7 +10,7 @@ Sunspot::GemTasks.new(:build => :copy_rdoc) do |s|
10
10
  s.description = <<TEXT
11
11
  Sunspot is a library providing a powerful, all-ruby API for the Solr search engine. Sunspot manages the configuration of persistent Ruby classes for search and indexing and exposes Solr's most powerful features through a collection of DSLs. Complex search operations can be performed without hand-writing any boolean queries or building Solr parameters by hand.
12
12
  TEXT
13
- s.authors = ['Mat Brown', 'Peer Allan', 'Dmitriy Dzema', 'Benjamin Krause', 'Marcel de Graaf', 'Brandon Keepers', 'Peter Berkenbosch', 'Brian Atkinson', 'Tom Coleman', 'Matt Mitchell', 'Nathan Beyer']
13
+ s.authors = ['Mat Brown', 'Peer Allan', 'Dmitriy Dzema', 'Benjamin Krause', 'Marcel de Graaf', 'Brandon Keepers', 'Peter Berkenbosch', 'Brian Atkinson', 'Tom Coleman', 'Matt Mitchell', 'Nathan Beyer', 'Kieran Topping', 'Nicolas Braem', 'Jeremy Ashkenas']
14
14
  s.rubyforge_project = 'sunspot'
15
15
  s.files = FileList['[A-Z]*', '{bin,installer,lib,spec,tasks,templates}/**/*', 'solr/{etc,lib,webapps}/**/*', 'solr/solr/{conf,lib}/*', 'solr/start.jar']
16
16
  s.add_runtime_dependency 'rsolr', '0.12.1'