benjaminkrause-sunspot 0.9.7 → 0.9.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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