outoftime-sunspot 0.8.5 → 0.8.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
@@ -29,7 +29,7 @@ objects such as the filesystem.
29
29
 
30
30
  In order to start the packaged Solr installation, run:
31
31
 
32
- sunspot-solr start -- [-d /path/to/data/directory] [-p port] [-s path/to/solr/home]
32
+ sunspot-solr start -- [-d /path/to/data/directory] [-p port] [-s path/to/solr/home] [--pid-dir=path/to/pid/dir]
33
33
 
34
34
  If you don't specify a data directory, your Solr index will be stored in your operating system's temporary directory.
35
35
 
@@ -146,6 +146,7 @@ http://outoftime.lighthouseapp.com/projects/20339-sunspot
146
146
  == Further Reading
147
147
 
148
148
  * Sunspot Discussion: http://groups.google.com/group/ruby-sunspot
149
+ * IRC: #sunspot-ruby @ Freenode
149
150
  * Posts about Sunspot from my tumblog: http://outofti.me/tagged/sunspot
150
151
  * Read about it on Linux Magazine: http://www.linux-mag.com/id/7341
151
152
 
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :major: 0
3
3
  :minor: 8
4
- :patch: 5
4
+ :patch: 8
data/bin/sunspot-solr CHANGED
@@ -24,14 +24,22 @@ module SolrFlags extend OptiFlagSet
24
24
  description 'Solr home (should contain conf/ directory)'
25
25
  end
26
26
 
27
+ optional_flag 'pd' do
28
+ long_form 'pid-dir'
29
+ description 'Directory for pid files'
30
+ end
31
+
27
32
  and_process!
28
33
  end
29
34
 
30
- port = ARGV.flags.p || '8983'
35
+ port = ARGV.flags.p || '8983'
31
36
  data_dir = File.expand_path(ARGV.flags.d || File.join(Dir.tmpdir, 'solr_data'))
32
- home = File.expand_path(ARGV.flags.s) if ARGV.flags.s
37
+ home = File.expand_path(ARGV.flags.s) if ARGV.flags.s
38
+ pid_dir = File.expand_path(ARGV.flags.pd || working_directory)
39
+
40
+ options = { :dir_mode => :normal, :dir => pid_dir }
33
41
 
34
- Daemons.run_proc('sunspot-solr') do
42
+ Daemons.run_proc('sunspot-solr', options) do
35
43
  FileUtils.cd(working_directory) do
36
44
  FileUtils.cd(solr_home) do
37
45
  args = ['java']
@@ -118,7 +118,7 @@ module Sunspot
118
118
  def for(clazz) #:nodoc:
119
119
  original_class_name = clazz.name
120
120
  clazz.ancestors.each do |ancestor_class|
121
- next if ancestor_class.name.empty?
121
+ next if ancestor_class.name.nil? || ancestor_class.name.empty?
122
122
  class_name = ancestor_class.name.to_sym
123
123
  return instance_adapters[class_name] if instance_adapters[class_name]
124
124
  end
@@ -227,14 +227,21 @@ module Sunspot
227
227
  #
228
228
  # ==== Returns
229
229
  #
230
- # Class:: Implementation of DataAccessor, or nil if none found
230
+ # Class:: Implementation of DataAccessor
231
+ #
232
+ # ==== Raises
233
+ #
234
+ # Sunspot::NoAdapterError:: If no data accessor exists for the given class
231
235
  #
232
236
  def for(clazz) #:nodoc:
237
+ original_class_name = clazz.name
233
238
  clazz.ancestors.each do |ancestor_class|
234
- next if ancestor_class.name.empty?
239
+ next if ancestor_class.name.nil? || ancestor_class.name.empty?
235
240
  class_name = ancestor_class.name.to_sym
236
241
  return data_accessors[class_name] if data_accessors[class_name]
237
242
  end
243
+ raise(Sunspot::NoAdapterError,
244
+ "No data accessor is configured for #{original_class_name} or its superclasses. See the documentation for Sunspot::Adapters")
238
245
  end
239
246
 
240
247
  protected
@@ -33,7 +33,7 @@ module Sunspot
33
33
  # Delete all documents of the class indexed by this indexer from Solr.
34
34
  #
35
35
  def remove_all
36
- @connection.delete_by_query("type:#{@setup.clazz.name}")
36
+ @connection.delete_by_query("type:#{Solr::Util.query_parser_escape(@setup.clazz.name)}")
37
37
  end
38
38
 
39
39
  protected
data/lib/sunspot/query.rb CHANGED
@@ -314,11 +314,18 @@ module Sunspot
314
314
  #
315
315
  def types_phrase
316
316
  if @types.nil? || @types.empty? then "type:[* TO *]"
317
- elsif @types.length == 1 then "type:#{@types.first}"
318
- else "type:(#{@types * ' OR '})"
317
+ elsif @types.length == 1 then "type:#{escaped_types.first}"
318
+ else "type:(#{escaped_types * ' OR '})"
319
319
  end
320
320
  end
321
321
 
322
+ #
323
+ # Wraps each type in quotes to escape names of the form Namespace::Class
324
+ #
325
+ def escaped_types
326
+ @types.map { |t| Solr::Util.query_parser_escape(t.name)}
327
+ end
328
+
322
329
  #
323
330
  # Return a hash of field names to field objects, containing all fields
324
331
  # that are common to all of the classes under search. In order for fields
data/lib/sunspot.rb CHANGED
@@ -347,7 +347,7 @@ module Sunspot
347
347
  # classes...<Class>::
348
348
  # classes for which to remove all instances from the index
349
349
  def remove_all!(*classes)
350
- session.remove_all(*classes)
350
+ session.remove_all!(*classes)
351
351
  end
352
352
 
353
353
  #
@@ -385,7 +385,7 @@ module Sunspot
385
385
  # static data between tests, but probably nowhere else.
386
386
  #
387
387
  def reset!
388
- @session = nil
388
+ @session = Session.new(session.config)
389
389
  end
390
390
 
391
391
  private
@@ -8,6 +8,12 @@ describe Sunspot::Adapters::InstanceAdapter do
8
8
  it "finds adapter by mixin" do
9
9
  Sunspot::Adapters::InstanceAdapter::for(MixModel).should be(MixInModelInstanceAdapter)
10
10
  end
11
+
12
+ it 'throws NoAdapterError if anonymous module passed in' do
13
+ lambda do
14
+ Sunspot::Adapters::InstanceAdapter::for(Module.new)
15
+ end.should raise_error(Sunspot::NoAdapterError)
16
+ end
11
17
  end
12
18
 
13
19
  describe Sunspot::Adapters::DataAccessor do
@@ -18,4 +24,10 @@ describe Sunspot::Adapters::DataAccessor do
18
24
  it "finds adapter by mixin" do
19
25
  Sunspot::Adapters::DataAccessor::for(MixModel).should be(MixInModelDataAccessor)
20
26
  end
27
+
28
+ it 'throws NoAdapterError if anonymous module passed in' do
29
+ lambda do
30
+ Sunspot::Adapters::DataAccessor::for(Module.new)
31
+ end.should raise_error(Sunspot::NoAdapterError)
32
+ end
21
33
  end
@@ -320,23 +320,28 @@ describe 'Search' do
320
320
  end
321
321
  end
322
322
 
323
+ it 'should properly escape namespaced type names' do
324
+ connection.should_receive(:query).with('(type:Namespaced\:\:Comment)', hash_including)
325
+ session.search(Namespaced::Comment)
326
+ end
327
+
323
328
  it 'should build search for multiple types' do
324
- connection.should_receive(:query).with('(type:(Post OR Comment))', hash_including)
325
- session.search(Post, Comment)
329
+ connection.should_receive(:query).with('(type:(Post OR Namespaced\:\:Comment))', hash_including)
330
+ session.search(Post, Namespaced::Comment)
326
331
  end
327
332
 
328
333
  it 'should allow search on fields common to all types' do
329
- connection.should_receive(:query).with('(type:(Post OR Comment))', hash_including(:filter_queries => ['published_at_d:1983\-07\-08T09\:00\:00Z'])).twice
334
+ connection.should_receive(:query).with('(type:(Post OR Namespaced\:\:Comment))', hash_including(:filter_queries => ['published_at_d:1983\-07\-08T09\:00\:00Z'])).twice
330
335
  time = Time.parse('1983-07-08 05:00:00 -0400')
331
- session.search Post, Comment, :conditions => { :published_at => time }
332
- session.search Post, Comment do
336
+ session.search Post, Namespaced::Comment, :conditions => { :published_at => time }
337
+ session.search Post, Namespaced::Comment do
333
338
  with :published_at, time
334
339
  end
335
340
  end
336
341
 
337
342
  it 'should raise Sunspot::UnrecognizedFieldError if search scoped to field not common to all types' do
338
343
  lambda do
339
- session.search Post, Comment do
344
+ session.search Post, Namespaced::Comment do
340
345
  with :blog_id, 1
341
346
  end
342
347
  end.should raise_error(Sunspot::UnrecognizedFieldError)
@@ -344,15 +349,15 @@ describe 'Search' do
344
349
 
345
350
  it 'should raise Sunspot::UnrecognizedFieldError if search scoped to field configured differently between types' do
346
351
  lambda do
347
- session.search Post, Comment do
352
+ session.search Post, Namespaced::Comment do
348
353
  with :average_rating, 2.2 # this is a float in Post but an integer in Comment
349
354
  end
350
355
  end.should raise_error(Sunspot::UnrecognizedFieldError)
351
356
  end
352
357
 
353
358
  it 'should ignore condition if field is not common to all types' do
354
- connection.should_receive(:query).with('(type:(Post OR Comment))', hash_not_including(:filter_queries))
355
- session.search Post, Comment, :conditions => { :blog_id => 1 }
359
+ connection.should_receive(:query).with('(type:(Post OR Namespaced\:\:Comment))', hash_not_including(:filter_queries))
360
+ session.search Post, Namespaced::Comment, :conditions => { :blog_id => 1 }
356
361
  end
357
362
 
358
363
  it 'should allow building search using block argument rather than instance_eval' do
@@ -15,10 +15,10 @@ describe 'indexer' do
15
15
  end
16
16
 
17
17
  it 'should index an array containing more than one type of object' do
18
- post1, comment, post2 = objects = [Post.new, Comment.new, Post.new]
18
+ post1, comment, post2 = objects = [Post.new, Namespaced::Comment.new, Post.new]
19
19
  connection.should_receive(:add).with([hash_including(:id => "Post #{post1.id}", :type => ['Post', 'BaseClass']),
20
20
  hash_including(:id => "Post #{post2.id}", :type => ['Post', 'BaseClass'])])
21
- connection.should_receive(:add).with([hash_including(:id => "Comment #{comment.id}", :type => ['Comment', 'BaseClass'])])
21
+ connection.should_receive(:add).with([hash_including(:id => "Namespaced::Comment #{comment.id}", :type => ['Namespaced::Comment', 'BaseClass'])])
22
22
  session.index objects
23
23
  end
24
24
 
@@ -134,6 +134,11 @@ describe 'indexer' do
134
134
  connection.should_receive(:delete_by_query).with("type:Post")
135
135
  session.remove_all(Post)
136
136
  end
137
+
138
+ it 'should correctly escape namespaced classes when removing everything from the index' do
139
+ connection.should_receive(:delete_by_query).with('type:Namespaced\:\:Comment')
140
+ session.remove_all(Namespaced::Comment)
141
+ end
137
142
  end
138
143
 
139
144
  describe 'dynamic fields' do
@@ -0,0 +1,20 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe Sunspot do
4
+ describe "reset!" do
5
+ it "should reset current session" do
6
+ old_session = Sunspot.send(:session)
7
+ Sunspot.reset!
8
+
9
+ Sunspot.send(:session).should_not == old_session
10
+ end
11
+ it "should keep keep configuration" do
12
+ Sunspot.config.solr.url = "http://localhost:9999/path/solr"
13
+
14
+ config_before_reset = Sunspot.config
15
+ Sunspot.reset!
16
+
17
+ Sunspot.config.should == config_before_reset
18
+ end
19
+ end
20
+ end
@@ -11,6 +11,8 @@ describe 'keyword search' do
11
11
  @posts << Post.new(:title => 'The toast abbreviates the recovering spirit',
12
12
  :body => 'Does the wind interpret the buffer?')
13
13
  Sunspot.index!(*@posts)
14
+ @comment = Namespaced::Comment.new(:body => 'Hey there where ya goin, not exactly knowin, who says you have to call just one place toast.')
15
+ Sunspot.index!(@comment)
14
16
  end
15
17
 
16
18
  it 'matches a single keyword out of a single field' do
@@ -29,4 +31,12 @@ describe 'keyword search' do
29
31
  [0, 2].each { |i| results.should include(@posts[i]) }
30
32
  [1].each { |i| results.should_not include(@posts[i]) }
31
33
  end
34
+
35
+ it 'matches multiple types' do
36
+ results = Sunspot.search(Post, Namespaced::Comment) do
37
+ keywords 'toast'
38
+ end.results
39
+ [@posts[0], @posts[2], @comment].each { |obj| results.should include(obj) }
40
+ results.should_not include(@posts[1])
41
+ end
32
42
  end
@@ -1,28 +1,30 @@
1
- class Comment < BaseClass
2
- @@id = 0
3
- @@comments = [nil]
1
+ module Namespaced
2
+ class Comment < BaseClass
3
+ @@id = 0
4
+ @@comments = [nil]
4
5
 
5
- attr_reader :id
6
- attr_accessor :author_name, :published_at, :body, :average_rating
6
+ attr_reader :id
7
+ attr_accessor :author_name, :published_at, :body, :average_rating
7
8
 
8
- def initialize(attrs = {})
9
- @id = @@id += 1
10
- @@comments << self
11
- attrs.each_pair { |attribute, value| self.send("#{attribute}=", value) }
12
- end
9
+ def initialize(attrs = {})
10
+ @id = @@id += 1
11
+ @@comments << self
12
+ attrs.each_pair { |attribute, value| self.send("#{attribute}=", value) }
13
+ end
13
14
 
14
- def self.get(id)
15
- @@posts[id]
16
- end
15
+ def self.get(id)
16
+ @@comments[id]
17
+ end
17
18
 
18
- def self.get_all(ids)
19
- ids.map { |id| get(id) }.sort_by { |post| post.id } # this is so that results are not ordered by coincidence
19
+ def self.get_all(ids)
20
+ ids.map { |id| get(id) }.sort_by { |post| post.id } # this is so that results are not ordered by coincidence
21
+ end
20
22
  end
21
- end
22
23
 
23
- Sunspot.setup(Comment) do
24
- text :author_name, :body
25
- string :author_name
26
- time :published_at
27
- integer :average_rating
24
+ Sunspot.setup(Comment) do
25
+ text :author_name, :body
26
+ string :author_name
27
+ time :published_at
28
+ integer :average_rating
29
+ end
28
30
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: outoftime-sunspot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.5
4
+ version: 0.8.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mat Brown
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-06-09 00:00:00 -07:00
12
+ date: 2009-06-15 00:00:00 -07:00
13
13
  default_executable: sunspot-solr
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -127,6 +127,7 @@ files:
127
127
  - spec/api/search_retrieval_spec.rb
128
128
  - spec/api/session_spec.rb
129
129
  - spec/api/spec_helper.rb
130
+ - spec/api/sunspot_spec.rb
130
131
  - spec/integration/dynamic_fields_spec.rb
131
132
  - spec/integration/faceting_spec.rb
132
133
  - spec/integration/keyword_search_spec.rb
@@ -195,5 +196,6 @@ test_files:
195
196
  - spec/api/session_spec.rb
196
197
  - spec/api/adapters_spec.rb
197
198
  - spec/api/build_search_spec.rb
199
+ - spec/api/sunspot_spec.rb
198
200
  - spec/api/indexer_spec.rb
199
201
  - spec/api/query_spec.rb