sunspot_rails 0.11.5 → 1.0.0

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.
@@ -0,0 +1,54 @@
1
+ module Sunspot
2
+ module Rails
3
+ module SolrLogging
4
+ class <<self
5
+ def included(base)
6
+ base.module_eval { alias_method_chain(:request, :rails_logging) }
7
+ end
8
+ end
9
+
10
+ def request_with_rails_logging(path, params={}, *extra)
11
+
12
+ # Set up logging text.
13
+ body = (params.nil? || params.empty?) ? extra.first : params.inspect
14
+ action = path[1..-1].capitalize
15
+ if body == "<commit/>"
16
+ action = 'Commit'
17
+ body = ''
18
+ end
19
+ body = body[0, 800] + '...' if body.length > 800
20
+
21
+ # Make request and log.
22
+ response = nil
23
+ begin
24
+ ms = Benchmark.ms do
25
+ response = request_without_rails_logging(path, params, *extra)
26
+ end
27
+ log_name = 'Solr %s (%.1fms)' % [action, ms]
28
+ ::Rails.logger.debug(format_log_entry(log_name, body))
29
+ rescue Exception => e
30
+ log_name = 'Solr %s (Error)' % [action]
31
+ ::Rails.logger.error(format_log_entry(log_name, body))
32
+ raise e
33
+ end
34
+
35
+ response
36
+ end
37
+
38
+ private
39
+
40
+ def format_log_entry(message, dump = nil)
41
+ if ActiveRecord::Base.colorize_logging
42
+ message_color, dump_color = "4;32;1", "0;1"
43
+ log_entry = " \e[#{message_color}m#{message}\e[0m "
44
+ log_entry << "\e[#{dump_color}m%#{String === dump ? 's' : 'p'}\e[0m" % dump if dump
45
+ log_entry
46
+ else
47
+ "%s %s" % [message, dump]
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ RSolr::Connection::Base.module_eval { include(Sunspot::Rails::SolrLogging) }
@@ -0,0 +1,19 @@
1
+ module Sunspot
2
+ module Rails
3
+ module SpecHelper
4
+ def disconnect_sunspot
5
+ before(:each) do
6
+ Sunspot.session = StubSessionProxy.new(Sunspot.session)
7
+ end
8
+
9
+ after(:each) do
10
+ Sunspot.session = Sunspot.session.original_session
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ Spec::Runner.configure do |config|
18
+ config.extend(Sunspot::Rails::SpecHelper)
19
+ end
@@ -0,0 +1,83 @@
1
+ module Sunspot
2
+ module Rails
3
+ class StubSessionProxy
4
+ attr_reader :original_session
5
+
6
+ def initialize(original_session)
7
+ @original_session = original_session
8
+ end
9
+
10
+ def index(*objects)
11
+ end
12
+
13
+ def index!(*objects)
14
+ end
15
+
16
+ def remove(*objects)
17
+ end
18
+
19
+ def remove!(*objects)
20
+ end
21
+
22
+ def remove_by_id(clazz, id)
23
+ end
24
+
25
+ def remove_by_id!(clazz, id)
26
+ end
27
+
28
+ def remove_all(clazz = nil)
29
+ end
30
+
31
+ def remove_all!(clazz = nil)
32
+ end
33
+
34
+ def dirty?
35
+ false
36
+ end
37
+
38
+ def delete_dirty?
39
+ false
40
+ end
41
+
42
+ def commit_if_dirty
43
+ end
44
+
45
+ def commit_if_delete_dirty
46
+ end
47
+
48
+ def commit
49
+ end
50
+
51
+ def search(*types)
52
+ Search.new
53
+ end
54
+
55
+ def new_search(*types)
56
+ Search.new
57
+ end
58
+
59
+ class Search
60
+ def results
61
+ []
62
+ end
63
+
64
+ def hits(options = {})
65
+ []
66
+ end
67
+
68
+ def total
69
+ 0
70
+ end
71
+
72
+ def facet(name)
73
+ end
74
+
75
+ def dynamic_facet(name)
76
+ end
77
+
78
+ def execute
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -5,12 +5,12 @@ namespace :sunspot do
5
5
  if RUBY_PLATFORM =~ /w(in)?32$/
6
6
  abort('This command does not work on Windows. Please use rake sunspot:solr:run to run Solr in the foreground.')
7
7
  end
8
- Sunspot::Rails::Server.start
8
+ Sunspot::Rails::Server.new.start
9
9
  end
10
10
 
11
11
  desc 'Run the Solr instance in the foreground'
12
12
  task :run => :environment do
13
- Sunspot::Rails::Server.run
13
+ Sunspot::Rails::Server.new.run
14
14
  end
15
15
 
16
16
  desc 'Stop the Solr instance'
@@ -18,18 +18,20 @@ namespace :sunspot do
18
18
  if RUBY_PLATFORM =~ /w(in)?32$/
19
19
  abort('This command does not work on Windows.')
20
20
  end
21
- Sunspot::Rails::Server.stop
21
+ Sunspot::Rails::Server.new.stop
22
22
  end
23
23
 
24
- desc 'Reindex all solr models'
25
- task :reindex => :environment do
26
- all_files = Dir.glob(File.join(RAILS_ROOT, 'app', 'models', '*.rb'))
27
- all_models = all_files.map { |path| File.basename(path, '.rb').camelize.constantize }
28
- sunspot_models = all_models.select { |m| m < ActiveRecord::Base and m.searchable? }
29
-
30
- sunspot_models.each do |model|
31
- model.reindex :batch_commit => false
32
- end
24
+ task :reindex => :"sunspot:reindex"
25
+ end
26
+
27
+ desc 'Reindex all solr models'
28
+ task :reindex => :environment do
29
+ all_files = Dir.glob(File.join(RAILS_ROOT, 'app', 'models', '*.rb'))
30
+ all_models = all_files.map { |path| File.basename(path, '.rb').camelize.constantize }
31
+ sunspot_models = all_models.select { |m| m < ActiveRecord::Base and m.searchable? }
32
+
33
+ sunspot_models.each do |model|
34
+ model.reindex :batch_commit => false
33
35
  end
34
36
  end
35
- end
37
+ end
@@ -1,5 +1,5 @@
1
1
  module Sunspot
2
2
  module Rails
3
- VERSION = '0.11.5'
3
+ VERSION = '1.0.0'
4
4
  end
5
5
  end
data/lib/sunspot/rails.rb CHANGED
@@ -1,12 +1,15 @@
1
1
  require 'sunspot'
2
- require 'sunspot/rails/configuration'
3
- require 'sunspot/rails/adapters'
4
- require 'sunspot/rails/request_lifecycle'
5
- require 'sunspot/rails/searchable'
6
- require 'sunspot/rails/util'
2
+ require File.join(File.dirname(__FILE__), 'rails', 'configuration')
3
+ require File.join(File.dirname(__FILE__), 'rails', 'adapters')
4
+ require File.join(File.dirname(__FILE__), 'rails', 'request_lifecycle')
5
+ require File.join(File.dirname(__FILE__), 'rails', 'searchable')
7
6
 
8
7
  module Sunspot #:nodoc:
9
8
  module Rails #:nodoc:
9
+ autoload :StubSessionProxy, File.join(File.dirname(__FILE__), 'rails', 'stub_session_proxy')
10
+ autoload :Server, File.join(File.dirname(__FILE__), 'rails', 'server')
11
+ autoload :VERSION, File.join(File.dirname(__FILE__), 'rails', 'version')
12
+
10
13
  class <<self
11
14
  attr_writer :configuration
12
15
 
@@ -15,7 +18,40 @@ module Sunspot #:nodoc:
15
18
  end
16
19
 
17
20
  def reset
18
- @master_session = @configuration = nil
21
+ @configuration = nil
22
+ end
23
+
24
+ def build_session(configuration = self.configuration)
25
+ if configuration.has_master?
26
+ SessionProxy::MasterSlaveSessionProxy.new(
27
+ SessionProxy::ThreadLocalSessionProxy.new(master_config(configuration)),
28
+ SessionProxy::ThreadLocalSessionProxy.new(slave_config(configuration))
29
+ )
30
+ else
31
+ SessionProxy::ThreadLocalSessionProxy.new(slave_config(configuration))
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def master_config(sunspot_rails_configuration)
38
+ config = Sunspot::Configuration.build
39
+ config.solr.url = URI::HTTP.build(
40
+ :host => sunspot_rails_configuration.master_hostname,
41
+ :port => sunspot_rails_configuration.master_port,
42
+ :path => sunspot_rails_configuration.master_path
43
+ ).to_s
44
+ config
45
+ end
46
+
47
+ def slave_config(sunspot_rails_configuration)
48
+ config = Sunspot::Configuration.build
49
+ config.solr.url = URI::HTTP.build(
50
+ :host => configuration.hostname,
51
+ :port => configuration.port,
52
+ :path => configuration.path
53
+ ).to_s
54
+ config
19
55
  end
20
56
  end
21
57
  end
data/rails/init.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'sunspot'
2
2
 
3
- Sunspot.session = Sunspot::Rails::SessionProxy.instance
3
+ Sunspot.session = Sunspot::Rails.build_session
4
4
  Sunspot::Adapters::InstanceAdapter.register(Sunspot::Rails::Adapters::ActiveRecordInstanceAdapter, ActiveRecord::Base)
5
5
  Sunspot::Adapters::DataAccessor.register(Sunspot::Rails::Adapters::ActiveRecordDataAccessor, ActiveRecord::Base)
6
6
  ActiveRecord::Base.module_eval { include(Sunspot::Rails::Searchable) }
@@ -0,0 +1,2 @@
1
+ class PhotoPost < PostWithAuto
2
+ end
@@ -1,6 +1,7 @@
1
1
  ActiveRecord::Schema.define(:version => 0) do
2
2
  create_table :posts, :force => true do |t|
3
3
  t.string :title
4
+ t.string :type
4
5
  t.text :body
5
6
  t.references :blog
6
7
  t.timestamps
@@ -1 +0,0 @@
1
- S
@@ -1,8 +1,6 @@
1
1
  require File.dirname(__FILE__) + '/spec_helper'
2
2
 
3
3
  describe 'searchable with lifecycle' do
4
- integrate_sunspot
5
-
6
4
  describe 'on create' do
7
5
  before :each do
8
6
  @post = PostWithAuto.create
@@ -24,6 +22,20 @@ describe 'searchable with lifecycle' do
24
22
  it 'should automatically update index' do
25
23
  PostWithAuto.search { with :title, 'Test 1' }.results.should == [@post]
26
24
  end
25
+
26
+ it "should index model if relevant attribute changed" do
27
+ @post = PostWithAuto.create!
28
+ @post.title = 'new title'
29
+ @post.should_receive :index
30
+ @post.save!
31
+ end
32
+
33
+ it "should not index model if relevant attribute not changed" do
34
+ @post = PostWithAuto.create!
35
+ @post.updated_at = Date.tomorrow
36
+ @post.should_not_receive :index
37
+ @post.save!
38
+ end
27
39
  end
28
40
 
29
41
  describe 'on destroy' do
@@ -40,8 +52,6 @@ describe 'searchable with lifecycle' do
40
52
  end
41
53
 
42
54
  describe 'searchable with lifecycle - ignoring specific attributes' do
43
- integrate_sunspot
44
-
45
55
  before(:each) do
46
56
  @post = PostWithAuto.create
47
57
  end
data/spec/model_spec.rb CHANGED
@@ -1,8 +1,6 @@
1
1
  require File.dirname(__FILE__) + '/spec_helper'
2
2
 
3
3
  describe 'ActiveRecord mixin' do
4
- integrate_sunspot
5
-
6
4
  describe 'index()' do
7
5
  before :each do
8
6
  @post = Post.create!
@@ -19,6 +17,17 @@ describe 'ActiveRecord mixin' do
19
17
  end
20
18
  end
21
19
 
20
+ describe 'single table inheritence' do
21
+ before :each do
22
+ @post = PhotoPost.create!
23
+ end
24
+
25
+ it 'should not break auto-indexing' do
26
+ @post.title = 'Title'
27
+ lambda { @post.save! }.should_not raise_error
28
+ end
29
+ end
30
+
22
31
  describe 'index!()' do
23
32
  before :each do
24
33
  @post = Post.create!
@@ -107,7 +116,7 @@ describe 'ActiveRecord mixin' do
107
116
  end
108
117
 
109
118
  it 'should find ActiveRecord objects with an integer, not a string' do
110
- Post.should_receive(:find).with([@post.id.to_i], anything()).and_return([@post])
119
+ Post.should_receive(:find_all_by_id).with([@post.id.to_i], anything).and_return([@post])
111
120
  Post.search do
112
121
  with :title, 'Test Post'
113
122
  end.results.should == [@post]
@@ -135,6 +144,16 @@ describe 'ActiveRecord mixin' do
135
144
  with :title, 'Test Post'
136
145
  end.results.should == [@post]
137
146
  end
147
+
148
+ it 'should gracefully handle nonexistent records' do
149
+ post2 = Post.create!(:title => 'Test Post')
150
+ post2.index!
151
+ post2.destroy
152
+ Post.search do
153
+ with :title, 'Test Post'
154
+ end.results.should == [@post]
155
+ end
156
+
138
157
  end
139
158
 
140
159
  describe 'search_ids()' do
@@ -233,8 +252,9 @@ describe 'ActiveRecord mixin' do
233
252
  Post.search.results.to_set.should == @posts.to_set
234
253
  end
235
254
  end
236
-
237
255
  end
256
+
257
+
238
258
 
239
259
  describe "reindex()" do
240
260
 
data/spec/schema.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  ActiveRecord::Schema.define(:version => 0) do
2
2
  create_table :posts, :force => true do |t|
3
3
  t.string :title
4
+ t.string :type
4
5
  t.text :body
5
6
  t.references :blog
6
7
  t.timestamps
data/spec/server_spec.rb CHANGED
@@ -1,124 +1,36 @@
1
1
  require File.join(File.dirname(__FILE__), 'spec_helper')
2
2
 
3
3
  describe Sunspot::Rails::Server do
4
- before(:each) do
5
- @sunspot_configuration = Sunspot::Rails::Configuration.new
4
+ before :each do
5
+ @server = Sunspot::Rails::Server.new
6
+ @solr_home = File.expand_path(File.join(Rails.root, 'solr'))
6
7
  end
7
8
 
8
- describe "rake task commands" do
9
- before(:each) do
10
- Sunspot::Rails::Server.should_receive(:pid_path).and_return('/tmp')
11
- end
12
-
13
- it "should generate and execute the start command" do
14
- Sunspot::Rails::Server.should_receive(:start_command).and_return('sunspot-start')
15
- Sunspot::Rails::Server.should_respond_to_and_receive(:bootstrap_neccessary?).and_return(false)
16
- Kernel.should_receive(:system).with('sunspot-start').and_return(true)
17
- Sunspot::Rails::Server.start.should == true
18
- end
19
-
20
- it "should generate and execute the stop command" do
21
- Sunspot::Rails::Server.should_receive(:stop_command).and_return('sunspot-stop')
22
- Sunspot::Rails::Server.should_not_receive(:bootstrap_neccessary?)
23
- Kernel.should_receive(:system).with('sunspot-stop').and_return(true)
24
- Sunspot::Rails::Server.stop.should == true
25
- end
26
-
27
- it "should generate and execute the run command" do
28
- Sunspot::Rails::Server.should_receive(:run_command).and_return('sunspot-run')
29
- Sunspot::Rails::Server.should_respond_to_and_receive(:bootstrap_neccessary?).and_return(false)
30
- Kernel.should_receive(:system).with('sunspot-run').and_return(true)
31
- Sunspot::Rails::Server.run.should == true
32
- end
9
+ it "sets the correct Solr home" do
10
+ @server.solr_home.should == @solr_home
33
11
  end
34
12
 
35
- describe "bootstraping" do
36
- before(:each) do
37
- @temp_dir = File.join( Dir.tmpdir, 'solr_rspec', Time.now.to_i.to_s, rand(1000).to_s )
38
- Sunspot::Rails::Server.should_receive(:solr_home).at_least(1).and_return( @temp_dir )
39
- end
40
-
41
- it "should require bootstraping" do
42
- Sunspot::Rails::Server.bootstrap_neccessary?.should == true
43
- end
44
-
45
- it "should not require bootstrapping again" do
46
- Sunspot::Rails::Server.bootstrap_neccessary?.should == true
47
- Sunspot::Rails::Server.bootstrap
48
- Sunspot::Rails::Server.bootstrap_neccessary?.should == false
49
- end
13
+ it "sets the correct Solr library path" do
14
+ @server.lib_path.should == File.join(@solr_home, 'lib')
50
15
  end
51
16
 
52
- describe "delegate methods" do
53
- before(:each) do
54
- Sunspot::Rails::Server.should_receive(:configuration).at_least(1).and_return(@sunspot_configuration)
55
- end
56
-
57
- it "should delegate the port method to the configuration" do
58
- @sunspot_configuration.should_respond_to_and_receive(:port).and_return(1234)
59
- Sunspot::Rails::Server.port.should == 1234
60
- end
61
-
62
- it "should delegate the solr_home method to the configuration" do
63
- @sunspot_configuration.should_respond_to_and_receive(:solr_home).and_return('/some/path')
64
- Sunspot::Rails::Server.solr_home.should == '/some/path'
65
- end
66
-
67
- it "should delegate the log_level method to the configuration" do
68
- @sunspot_configuration.should_respond_to_and_receive(:log_level).and_return('LOG_LEVEL')
69
- Sunspot::Rails::Server.log_level.should == 'LOG_LEVEL'
70
- end
71
-
72
- it "should delegate the log_dir method to the configuration" do
73
- @sunspot_configuration.should_respond_to_and_receive(:log_file).and_return('log_file')
74
- Sunspot::Rails::Server.log_file.should =~ /log_file/
75
- end
17
+ it "sets the correct Solr PID path" do
18
+ @server.pid_path.should == File.join(Rails.root, 'tmp', 'pids', 'sunspot-solr-test.pid')
19
+ end
76
20
 
21
+ it "sets the correct Solr data dir" do
22
+ @server.solr_data_dir.should == File.join(@solr_home, 'data', 'test')
77
23
  end
78
24
 
79
- describe "protected methods" do
80
- it "should generate the start command" do
81
- Sunspot::Rails::Server.should_respond_to_and_receive(:port).and_return('1')
82
- Sunspot::Rails::Server.should_respond_to_and_receive(:solr_home).and_return('home')
83
- Sunspot::Rails::Server.should_respond_to_and_receive(:data_path).and_return('data')
84
- Sunspot::Rails::Server.should_respond_to_and_receive(:log_level).and_return('LOG')
85
- Sunspot::Rails::Server.should_respond_to_and_receive(:log_file).and_return('log_file')
86
- Sunspot::Rails::Server.send(:start_command).should == \
87
- [ 'sunspot-solr', 'start', '-p', '1', '-d', 'data', '-s', 'home', '-l', 'LOG', '--log-file', 'log_file' ]
88
- end
89
-
90
- it "should generate the stop command" do
91
- Sunspot::Rails::Server.send(:stop_command).should == [ 'sunspot-solr', 'stop' ]
92
- end
93
-
94
- it "should generate the run command" do
95
- Sunspot::Rails::Server.should_respond_to_and_receive(:port).and_return('1')
96
- Sunspot::Rails::Server.should_respond_to_and_receive(:solr_home).and_return('home')
97
- Sunspot::Rails::Server.should_respond_to_and_receive(:data_path).and_return('data')
98
- Sunspot::Rails::Server.should_respond_to_and_receive(:log_level).and_return('LOG')
99
- Sunspot::Rails::Server.should_respond_to_and_receive(:log_file).and_return('log_file')
100
- Sunspot::Rails::Server.send(:run_command).should == \
101
- [ 'sunspot-solr', 'run', '-p', '1', '-d', 'data', '-s', 'home', '-l', 'LOG', '-lf', 'log_file' ]
102
- end
25
+ it "sets the correct port" do
26
+ @server.port.should == 8980
27
+ end
103
28
 
104
- it "should generate the path for config files" do
105
- Sunspot::Rails::Server.should_receive(:solr_home).and_return('/solr/home')
106
- Sunspot::Rails::Server.config_path.should == '/solr/home/conf'
107
- end
108
-
109
- it "should generate the path for custom libraries" do
110
- Sunspot::Rails::Server.should_receive(:solr_home).and_return('/solr/home')
111
- Sunspot::Rails::Server.lib_path.should == '/solr/home/lib'
112
- end
113
-
114
- it "should generate the path for the index data" do
115
- Sunspot::Rails::Server.should_receive(:solr_home).and_return('/solr/home')
116
- Sunspot::Rails::Server.data_path.should == '/solr/home/data/test'
117
- end
29
+ it "sets the correct log level" do
30
+ @server.log_level.should == "FINE"
31
+ end
118
32
 
119
- it "should generate the path for pid files" do
120
- Sunspot::Rails::Server.should_receive(:solr_home).and_return('/solr/home')
121
- Sunspot::Rails::Server.pid_path.should == '/solr/home/pids/test'
122
- end
33
+ it "sets the correct log file" do
34
+ @server.log_file.should == File.join(Rails.root, 'log', 'sunspot-solr-test.log')
123
35
  end
124
- end
36
+ end
data/spec/spec_helper.rb CHANGED
@@ -12,8 +12,7 @@ require 'spec'
12
12
  require 'spec/rails'
13
13
  require 'rake'
14
14
  require 'ruby-debug' unless RUBY_VERSION > '1.9'
15
- require 'sunspot/rails/tasks'
16
- require 'sunspot/spec/extension'
15
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'sunspot', 'rails', 'solr_logging')
17
16
 
18
17
  def load_schema
19
18
  stdout = $stdout
@@ -31,11 +30,8 @@ end
31
30
 
32
31
  Spec::Runner.configure do |config|
33
32
  config.before(:each) do
34
- if integrate_sunspot?
35
- Sunspot.remove_all
36
- Sunspot.commit
37
- end
38
33
  load_schema
34
+ Sunspot.remove_all!
39
35
  end
40
36
  end
41
37