benjaminkrause-sunspot 0.9.7 → 0.9.8

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -152,7 +152,10 @@ http://outoftime.lighthouseapp.com/projects/20339-sunspot
152
152
  * Peer Allan (peer.allan@gmail.com)
153
153
  * Dmitriy Dzema (dima@dzema.name)
154
154
  * Benjamin Krause (bk@benjaminkrause.com)
155
+ * Marcel de Graaf (marcel@slashdev.nl)
155
156
  * Brandon Keepers (brandon@opensoul.org)
157
+ * Peter Berkenbosch (peterberkenbosch@me.com)
158
+ * Brian Atkinson
156
159
 
157
160
  == License
158
161
 
data/TODO CHANGED
@@ -1,5 +1,5 @@
1
1
  === 0.10 ===
2
- * Pass highlight fields into #highlight varargs
2
+ * Wrap everything into :q parameter when local search performed
3
3
  * Allow boosting without field constraints
4
4
  * Allow coordinates to be specified with block in setup
5
5
  === 0.11 ===
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :minor: 9
3
- :patch: 7
3
+ :patch: 8
4
4
  :major: 0
data/bin/sunspot-solr CHANGED
@@ -77,7 +77,7 @@ Daemons.run_proc('sunspot-solr', options) do
77
77
  args << "-Djetty.port=#{port}" if port
78
78
  args << "-Dsolr.data.dir=#{data_dir}" if data_dir
79
79
  args << "-Dsolr.solr.home=#{home}" if home
80
- args << "-Djava.util.logging.config.file=#{logging_properties(log_file, log_level)}" if log_file and log_file != 'OFF'
80
+ args << "-Djava.util.logging.config.file=#{logging_properties(log_file, log_level)}" if log_file and log_level != 'OFF'
81
81
  args << '-jar' << 'start.jar'
82
82
  STDERR.puts(args * ' ')
83
83
  Kernel.exec(*args)
@@ -28,6 +28,9 @@ module Sunspot
28
28
  solr do
29
29
  url 'http://127.0.0.1:8983/solr'
30
30
  end
31
+ master_solr do
32
+ url nil
33
+ end
31
34
  pagination do
32
35
  default_per_page 30
33
36
  end
@@ -17,7 +17,7 @@ module Sunspot
17
17
  # === Example
18
18
  #
19
19
  # Sunspot.search(Post) do
20
- # fulltext 'search is cool' do
20
+ # keywords 'search is cool' do
21
21
  # fields(:body, :title => 2.0)
22
22
  # end
23
23
  # end
@@ -36,7 +36,15 @@ module Sunspot
36
36
  end
37
37
 
38
38
  #
39
- # Enable keyword highlighting for this search. Options are the following:
39
+ # Enable keyword highlighting for this search. By default, the fields
40
+ # under search will be highlighted; you may also may pass one or more
41
+ # symbol arguments indicating fields to be highlighted (they don't even
42
+ # have to be the same fields you're searching).
43
+ #
44
+ # highlight :title, :body
45
+ #
46
+ # You may also pass a hash of options as the last argument. Options are
47
+ # the following:
40
48
  #
41
49
  # Full disclosure: I barely understand what these options actually do;
42
50
  # this documentation is pretty much just copied from the
@@ -56,8 +64,11 @@ module Sunspot
56
64
  # this particular field (only has an effect if :phrase_highlighter is
57
65
  # true as well)
58
66
  #
59
- def highlight(options = {})
60
- @query.set_highlight(options)
67
+ def highlight(*args)
68
+ options = args.last.kind_of?(Hash) ? args.pop : {}
69
+ fields = args
70
+
71
+ @query.set_highlight(fields, options)
61
72
  end
62
73
 
63
74
  #
@@ -4,13 +4,11 @@ module Sunspot
4
4
  def initialize(keywords, options, types, setup)
5
5
  super(types, setup)
6
6
  @keywords = keywords
7
+
7
8
  if highlight_options = options.delete(:highlight)
8
- if highlight_options == true
9
- set_highlight
10
- else
11
- set_highlight(highlight_options)
12
- end
9
+ set_highlight(highlight_options == true ? [] : highlight_options)
13
10
  end
11
+
14
12
  if fulltext_fields = options.delete(:fields)
15
13
  Array(fulltext_fields).each do |field|
16
14
  add_fulltext_field(field)
@@ -58,12 +56,18 @@ module Sunspot
58
56
  @boost_query ||= BoostQuery.new(factor, @setup)
59
57
  end
60
58
 
61
- def set_highlight(options = {})
62
- @highlight = Highlighting.new(options)
59
+ def set_highlight(field_names=[], options={})
60
+ @highlight = Highlighting.new(text_fields(field_names), options)
63
61
  end
64
62
 
65
63
  private
66
64
 
65
+ def text_fields(field_names)
66
+ field_names.inject([]) do |fields, name|
67
+ fields.concat(@setup.text_fields(name))
68
+ end
69
+ end
70
+
67
71
  #
68
72
  # Returns the names of text fields that should be queried in a keyword
69
73
  # search. If specific fields are requested, use those; otherwise use the
@@ -4,7 +4,8 @@ module Sunspot
4
4
  # A query component that builds parameters for requesting highlights
5
5
  #
6
6
  class Highlighting #:nodoc:
7
- def initialize(options)
7
+ def initialize(fields=[], options={})
8
+ @fields = fields
8
9
  @options = options
9
10
  end
10
11
 
@@ -14,6 +15,9 @@ module Sunspot
14
15
  :"hl.simple.pre" => '@@@hl@@@',
15
16
  :"hl.simple.post" => '@@@endhl@@@'
16
17
  }
18
+ unless @fields.empty?
19
+ params[:"hl.fl"] = @fields.map { |field| field.indexed_name }
20
+ end
17
21
  if max_snippets = @options[:max_snippets]
18
22
  params[:"hl.snippets"] = max_snippets
19
23
  end
@@ -15,7 +15,7 @@ module Sunspot
15
15
  # For testing purposes
16
16
  #
17
17
  def connection_class #:nodoc:
18
- @connection_class ||= RSolr::Connection
18
+ @connection_class ||= RSolr
19
19
  end
20
20
  end
21
21
 
@@ -29,10 +29,11 @@ module Sunspot
29
29
  # connection. Usually you will want to stick with the default arguments
30
30
  # when instantiating your own sessions.
31
31
  #
32
- def initialize(config = Configuration.build, connection = nil)
32
+ def initialize(config = Configuration.build, connection = nil, master_connection = nil)
33
33
  @config = config
34
34
  yield(@config) if block_given?
35
35
  @connection = connection
36
+ @master_connection = master_connection
36
37
  @updates = 0
37
38
  end
38
39
 
@@ -84,7 +85,7 @@ module Sunspot
84
85
  #
85
86
  def commit
86
87
  @updates = 0
87
- connection.commit
88
+ master_connection.commit
88
89
  end
89
90
 
90
91
  #
@@ -134,7 +135,7 @@ module Sunspot
134
135
  classes.flatten!
135
136
  if classes.empty?
136
137
  @updates += 1
137
- Indexer.remove_all(connection)
138
+ Indexer.remove_all(master_connection)
138
139
  else
139
140
  @updates += classes.length
140
141
  for clazz in classes
@@ -187,20 +188,40 @@ module Sunspot
187
188
  def connection
188
189
  @connection ||=
189
190
  begin
190
- connection = self.class.connection_class.new(
191
- RSolr::Adapter::HTTP.new(:url => config.solr.url)
192
- )
193
- connection.adapter.connector.adapter_name = config.http_client
194
- connection
191
+ self.class.connection_class.connect(:url => config.solr.url, :adapter => config.http_client)
192
+ # connection = self.class.connection_class.new(
193
+ # RSolr::Adapter::HTTP.new(:url => config.solr.url)
194
+ # )
195
+ # connection.adapter.connector.adapter_name = config.http_client
196
+ # connection
195
197
  end
196
198
  end
197
199
 
198
200
  #
199
- # Return an indexer pointing at this session's connection. One is created
200
- # and saved for each sesion.
201
+ # Retrieve the Solr connection to the master for this session, creating one
202
+ # if it does not already exist.
201
203
  #
204
+ # ==== Returns
205
+ #
206
+ # Solr::Connection:: The connection for this session
207
+ #
208
+ def master_connection
209
+ @master_connection ||=
210
+ begin
211
+ if config.master_solr.url && config.master_solr.url != config.solr.url
212
+ master_connection = self.class.connection_class.new(
213
+ RSolr::Adapter::HTTP.new(:url => config.master_solr.url)
214
+ )
215
+ master_connection.adapter.connector.adapter_name = config.http_client
216
+ master_connection
217
+ else
218
+ connection
219
+ end
220
+ end
221
+ end
222
+
202
223
  def indexer
203
- @indexer ||= Indexer.new(connection)
224
+ @indexer ||= Indexer.new(master_connection)
204
225
  end
205
226
  end
206
227
  end
data/lib/sunspot/util.rb CHANGED
@@ -66,7 +66,7 @@ module Sunspot
66
66
  #
67
67
  def full_const_get(string)
68
68
  string.split('::').inject(Object) do |context, const_name|
69
- context.const_get(const_name)
69
+ context.const_defined?(const_name) ? context.const_get(const_name) : context.const_missing(const_name)
70
70
  end
71
71
  end
72
72
 
@@ -15,6 +15,42 @@ describe 'highlighted fulltext queries', :type => :query do
15
15
  connection.should have_last_search_with(:hl => 'on')
16
16
  end
17
17
 
18
+ it 'should enable highlighting on multiple fields when highlighting requested as array of fields via keywords argument' do
19
+ session.search(Post) do
20
+ keywords 'test', :highlight => [:title, :body]
21
+ end
22
+
23
+ connection.should have_last_search_with(:hl => 'on', :'hl.fl' => %w(title_text body_texts))
24
+ end
25
+
26
+ it 'should raise UnrecognizedFieldError if try to highlight unexisting field via keywords argument' do
27
+ lambda {
28
+ session.search(Post) do
29
+ keywords 'test', :highlight => [:unknown_field]
30
+ end
31
+ }.should raise_error(Sunspot::UnrecognizedFieldError)
32
+ end
33
+
34
+ it 'should enable highlighting on multiple fields when highlighting requested as list of fields via block call' do
35
+ session.search(Post) do
36
+ keywords 'test' do
37
+ highlight :title, :body
38
+ end
39
+ end
40
+
41
+ connection.should have_last_search_with(:hl => 'on', :'hl.fl' => %w(title_text body_texts))
42
+ end
43
+
44
+ it 'should raise UnrecognizedFieldError if try to highlight unexisting field via block call' do
45
+ lambda {
46
+ session.search(Post) do
47
+ keywords 'test' do
48
+ highlight :unknown_field
49
+ end
50
+ end
51
+ }.should raise_error(Sunspot::UnrecognizedFieldError)
52
+ end
53
+
18
54
  it 'should set internal formatting' do
19
55
  session.search(Post) do
20
56
  keywords 'test', :highlight => true
@@ -25,6 +61,18 @@ describe 'highlighted fulltext queries', :type => :query do
25
61
  )
26
62
  end
27
63
 
64
+ it 'should set options and hihglight fields' do
65
+ session.search(Post) do
66
+ keywords 'test' do
67
+ highlight :title, :max_snippets => 3
68
+ end
69
+ end
70
+ connection.should have_last_search_with(
71
+ :"hl.fl" => %w(title_text),
72
+ :"hl.snippets" => 3
73
+ )
74
+ end
75
+
28
76
  it 'should set maximum highlights per field' do
29
77
  session.search(Post) do
30
78
  keywords 'test' do
@@ -79,4 +127,5 @@ describe 'highlighted fulltext queries', :type => :query do
79
127
  :"hl.requireFieldMatch" => 'true'
80
128
  )
81
129
  end
130
+
82
131
  end
@@ -67,24 +67,24 @@ describe 'Session' do
67
67
 
68
68
  it 'should open connection with defaults if nothing specified' do
69
69
  Sunspot.commit
70
- connection.adapter.opts[:url].should == 'http://127.0.0.1:8983/solr'
70
+ connection.opts[:url].should == 'http://127.0.0.1:8983/solr'
71
71
  end
72
72
 
73
73
  it 'should open a connection with custom host' do
74
74
  Sunspot.config.solr.url = 'http://127.0.0.1:8981/solr'
75
75
  Sunspot.commit
76
- connection.adapter.opts[:url].should == 'http://127.0.0.1:8981/solr'
76
+ connection.opts[:url].should == 'http://127.0.0.1:8981/solr'
77
77
  end
78
78
 
79
79
  it 'should use Net::HTTP adapter by default' do
80
80
  Sunspot.commit
81
- connection.adapter.connector.adapter_name.should == :net_http
81
+ connection.adapter.should == :net_http
82
82
  end
83
83
 
84
84
  it 'should use Net::HTTP adapter when specified' do
85
85
  Sunspot.config.http_client = :curb
86
86
  Sunspot.commit
87
- connection.adapter.connector.adapter_name.should == :curb
87
+ connection.adapter.should == :curb
88
88
  end
89
89
  end
90
90
 
@@ -100,7 +100,7 @@ describe 'Session' do
100
100
  config.solr.url = 'http://127.0.0.1:8982/solr'
101
101
  end
102
102
  session.commit
103
- connection.adapter.opts[:url].should == 'http://127.0.0.1:8982/solr'
103
+ connection.opts[:url].should == 'http://127.0.0.1:8982/solr'
104
104
  end
105
105
  end
106
106
 
@@ -69,7 +69,7 @@ module SearchHelper
69
69
  end
70
70
 
71
71
  def connection
72
- @connection ||= mock('connection')
72
+ @connection ||= Mock::Connection.new
73
73
  end
74
74
 
75
75
  def session
@@ -29,6 +29,15 @@ describe 'local search' do
29
29
  search.results.should == [@posts[1]]
30
30
  end
31
31
 
32
+ it 'should perform a radial search with attribute scoping' do
33
+ pending 'local/scope workaround'
34
+ search = Sunspot.search(Post) do |query|
35
+ query.near(ORIGIN,20)
36
+ query.with(:title, 'teacup')
37
+ end
38
+ search.results.should == [@posts[1]]
39
+ end
40
+
32
41
  it 'should order by arbitrary field' do
33
42
  search = Sunspot.search(Post) do |query|
34
43
  query.near(ORIGIN, 20)
@@ -1 +1,7 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ Spec::Runner.configure do |config|
4
+ config.before(:each) do
5
+ Sunspot.config.solr.url = ENV['SOLR_URL'] || 'http://localhost:8983/solr'
6
+ end
7
+ end
@@ -1,5 +1,13 @@
1
1
  module Mock
2
2
  class ConnectionFactory
3
+ def connect(opts)
4
+ if @instance
5
+ raise('Factory can only create an instance once!')
6
+ else
7
+ @instance = Connection.new(opts.delete(:adapter), opts)
8
+ end
9
+ end
10
+
3
11
  def new(adapter = nil, opts = nil)
4
12
  if @instance
5
13
  raise('Factory can only create an instance once!')
data/tasks/gemspec.rake CHANGED
@@ -10,10 +10,10 @@ begin
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', 'Brandon Keepers']
13
+ s.authors = ['Mat Brown', 'Peer Allan', 'Dmitriy Dzema', 'Benjamin Krause', 'Marcel de Graaf', 'Brandon Keepers', 'Peter Berkenbosch', 'Brian Atkinson']
14
14
  s.rubyforge_project = 'sunspot'
15
15
  s.files = FileList['[A-Z]*', '{bin,lib,spec,tasks,templates}/**/*', 'solr/{etc,lib,webapps}/**/*', 'solr/solr/conf/*', 'solr/start.jar']
16
- s.add_dependency 'mwmitchell-rsolr', '= 0.9.1'
16
+ s.add_dependency 'mwmitchell-rsolr', '= 0.9.6'
17
17
  s.add_dependency 'daemons', '~> 1.0'
18
18
  s.add_dependency 'optiflag', '~> 0.6.5'
19
19
  s.add_development_dependency 'rspec', '~> 1.1'
metadata CHANGED
@@ -1,19 +1,22 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: benjaminkrause-sunspot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.7
4
+ version: 0.9.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mat Brown
8
8
  - Peer Allan
9
9
  - Dmitriy Dzema
10
10
  - Benjamin Krause
11
+ - Marcel de Graaf
11
12
  - Brandon Keepers
13
+ - Peter Berkenbosch
14
+ - Brian Atkinson
12
15
  autorequire:
13
16
  bindir: bin
14
17
  cert_chain: []
15
18
 
16
- date: 2009-09-16 00:00:00 -07:00
19
+ date: 2009-09-21 00:00:00 -07:00
17
20
  default_executable:
18
21
  dependencies:
19
22
  - !ruby/object:Gem::Dependency
@@ -24,7 +27,7 @@ dependencies:
24
27
  requirements:
25
28
  - - "="
26
29
  - !ruby/object:Gem::Version
27
- version: 0.9.1
30
+ version: 0.9.6
28
31
  version:
29
32
  - !ruby/object:Gem::Dependency
30
33
  name: daemons
@@ -253,60 +256,60 @@ requirements: []
253
256
  rubyforge_project: sunspot
254
257
  rubygems_version: 1.3.5
255
258
  signing_key:
256
- specification_version: 2
259
+ specification_version: 3
257
260
  summary: Library for expressive, powerful interaction with the Solr search engine
258
261
  test_files:
259
- - spec/api/adapters_spec.rb
260
- - spec/api/indexer/attributes_spec.rb
261
- - spec/api/indexer/batch_spec.rb
262
- - spec/api/indexer/dynamic_fields_spec.rb
263
- - spec/api/indexer/fixed_fields_spec.rb
264
- - spec/api/indexer/fulltext_spec.rb
265
- - spec/api/indexer/removal_spec.rb
266
- - spec/api/indexer/spec_helper.rb
267
- - spec/api/indexer_spec.rb
268
- - spec/api/query/connectives_spec.rb
269
- - spec/api/query/dsl_spec.rb
270
- - spec/api/query/dynamic_fields_spec.rb
271
- - spec/api/query/faceting_spec.rb
272
- - spec/api/query/fulltext_spec.rb
273
- - spec/api/query/highlighting_spec.rb
274
- - spec/api/query/local_spec.rb
275
- - spec/api/query/ordering_pagination_spec.rb
276
- - spec/api/query/scope_spec.rb
277
- - spec/api/query/spec_helper.rb
278
- - spec/api/query/text_field_scoping_spec.rb
279
- - spec/api/query/types_spec.rb
280
- - spec/api/search/dynamic_fields_spec.rb
281
- - spec/api/search/faceting_spec.rb
282
- - spec/api/search/highlighting_spec.rb
283
- - spec/api/search/hits_spec.rb
284
- - spec/api/search/results_spec.rb
285
- - spec/api/search/search_spec.rb
286
- - spec/api/search/spec_helper.rb
287
- - spec/api/session_spec.rb
288
- - spec/api/spec_helper.rb
289
- - spec/api/sunspot_spec.rb
262
+ - spec/spec_helper.rb
290
263
  - spec/helpers/indexer_helper.rb
291
- - spec/helpers/query_helper.rb
292
264
  - spec/helpers/search_helper.rb
293
- - spec/integration/dynamic_fields_spec.rb
265
+ - spec/helpers/query_helper.rb
266
+ - spec/integration/spec_helper.rb
267
+ - spec/integration/local_search_spec.rb
294
268
  - spec/integration/faceting_spec.rb
269
+ - spec/integration/scoped_search_spec.rb
295
270
  - spec/integration/highlighting_spec.rb
296
271
  - spec/integration/keyword_search_spec.rb
297
- - spec/integration/local_search_spec.rb
298
- - spec/integration/scoped_search_spec.rb
299
- - spec/integration/spec_helper.rb
272
+ - spec/integration/dynamic_fields_spec.rb
300
273
  - spec/integration/stored_fields_spec.rb
301
274
  - spec/integration/test_pagination.rb
302
- - spec/mocks/adapters.rb
275
+ - spec/mocks/mock_record.rb
303
276
  - spec/mocks/blog.rb
304
- - spec/mocks/comment.rb
305
- - spec/mocks/connection.rb
277
+ - spec/mocks/adapters.rb
306
278
  - spec/mocks/mock_adapter.rb
307
- - spec/mocks/mock_record.rb
279
+ - spec/mocks/user.rb
308
280
  - spec/mocks/photo.rb
309
281
  - spec/mocks/post.rb
282
+ - spec/mocks/comment.rb
310
283
  - spec/mocks/super_class.rb
311
- - spec/mocks/user.rb
312
- - spec/spec_helper.rb
284
+ - spec/mocks/connection.rb
285
+ - spec/api/spec_helper.rb
286
+ - spec/api/session_spec.rb
287
+ - spec/api/indexer/spec_helper.rb
288
+ - spec/api/indexer/fixed_fields_spec.rb
289
+ - spec/api/indexer/attributes_spec.rb
290
+ - spec/api/indexer/dynamic_fields_spec.rb
291
+ - spec/api/indexer/fulltext_spec.rb
292
+ - spec/api/indexer/removal_spec.rb
293
+ - spec/api/indexer/batch_spec.rb
294
+ - spec/api/search/spec_helper.rb
295
+ - spec/api/search/hits_spec.rb
296
+ - spec/api/search/faceting_spec.rb
297
+ - spec/api/search/highlighting_spec.rb
298
+ - spec/api/search/dynamic_fields_spec.rb
299
+ - spec/api/search/search_spec.rb
300
+ - spec/api/search/results_spec.rb
301
+ - spec/api/adapters_spec.rb
302
+ - spec/api/query/dsl_spec.rb
303
+ - spec/api/query/spec_helper.rb
304
+ - spec/api/query/faceting_spec.rb
305
+ - spec/api/query/connectives_spec.rb
306
+ - spec/api/query/local_spec.rb
307
+ - spec/api/query/highlighting_spec.rb
308
+ - spec/api/query/ordering_pagination_spec.rb
309
+ - spec/api/query/dynamic_fields_spec.rb
310
+ - spec/api/query/types_spec.rb
311
+ - spec/api/query/scope_spec.rb
312
+ - spec/api/query/text_field_scoping_spec.rb
313
+ - spec/api/query/fulltext_spec.rb
314
+ - spec/api/sunspot_spec.rb
315
+ - spec/api/indexer_spec.rb