outoftime-sunspot 0.8.5 → 0.8.8

Sign up to get free protection for your applications and to get access to all the features.
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