erichummel-sunspot_rails 1.2.1a
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/History.txt +51 -0
- data/LICENSE +18 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +258 -0
- data/Rakefile +18 -0
- data/TESTING.md +35 -0
- data/TODO +8 -0
- data/VERSION.yml +4 -0
- data/dev_tasks/rdoc.rake +24 -0
- data/dev_tasks/release.rake +4 -0
- data/dev_tasks/spec.rake +22 -0
- data/dev_tasks/todo.rake +4 -0
- data/generators/sunspot/sunspot_generator.rb +9 -0
- data/generators/sunspot/templates/sunspot.yml +18 -0
- data/install.rb +1 -0
- data/lib/generators/sunspot_rails/install/install_generator.rb +13 -0
- data/lib/generators/sunspot_rails/install/templates/config/sunspot.yml +17 -0
- data/lib/generators/sunspot_rails.rb +9 -0
- data/lib/sunspot/rails/adapters.rb +83 -0
- data/lib/sunspot/rails/configuration.rb +323 -0
- data/lib/sunspot/rails/init.rb +5 -0
- data/lib/sunspot/rails/log_subscriber.rb +33 -0
- data/lib/sunspot/rails/railtie.rb +36 -0
- data/lib/sunspot/rails/railties/controller_runtime.rb +36 -0
- data/lib/sunspot/rails/request_lifecycle.rb +36 -0
- data/lib/sunspot/rails/searchable.rb +412 -0
- data/lib/sunspot/rails/server.rb +173 -0
- data/lib/sunspot/rails/solr_instrumentation.rb +21 -0
- data/lib/sunspot/rails/solr_logging.rb +63 -0
- data/lib/sunspot/rails/spec_helper.rb +26 -0
- data/lib/sunspot/rails/stub_session_proxy.rb +88 -0
- data/lib/sunspot/rails/tasks.rb +62 -0
- data/lib/sunspot/rails/version.rb +5 -0
- data/lib/sunspot/rails.rb +59 -0
- data/lib/sunspot_rails.rb +12 -0
- data/spec/configuration_spec.rb +173 -0
- data/spec/model_lifecycle_spec.rb +63 -0
- data/spec/model_spec.rb +356 -0
- data/spec/request_lifecycle_spec.rb +61 -0
- data/spec/schema.rb +27 -0
- data/spec/server_spec.rb +37 -0
- data/spec/session_spec.rb +24 -0
- data/spec/spec_helper.rb +46 -0
- data/spec/stub_session_proxy_spec.rb +122 -0
- metadata +155 -0
@@ -0,0 +1,88 @@
|
|
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 build
|
61
|
+
self
|
62
|
+
end
|
63
|
+
|
64
|
+
def results
|
65
|
+
[]
|
66
|
+
end
|
67
|
+
|
68
|
+
def hits(options = {})
|
69
|
+
[]
|
70
|
+
end
|
71
|
+
|
72
|
+
def total
|
73
|
+
0
|
74
|
+
end
|
75
|
+
|
76
|
+
def facet(name)
|
77
|
+
end
|
78
|
+
|
79
|
+
def dynamic_facet(name)
|
80
|
+
end
|
81
|
+
|
82
|
+
def execute
|
83
|
+
self
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
namespace :sunspot do
|
2
|
+
namespace :solr do
|
3
|
+
desc 'Start the Solr instance'
|
4
|
+
task :start => :environment do
|
5
|
+
if RUBY_PLATFORM =~ /w(in)?32$/
|
6
|
+
abort('This command does not work on Windows. Please use rake sunspot:solr:run to run Solr in the foreground.')
|
7
|
+
end
|
8
|
+
Sunspot::Rails::Server.new.start
|
9
|
+
end
|
10
|
+
|
11
|
+
desc 'Run the Solr instance in the foreground'
|
12
|
+
task :run => :environment do
|
13
|
+
Sunspot::Rails::Server.new.run
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'Stop the Solr instance'
|
17
|
+
task :stop => :environment do
|
18
|
+
if RUBY_PLATFORM =~ /w(in)?32$/
|
19
|
+
abort('This command does not work on Windows.')
|
20
|
+
end
|
21
|
+
Sunspot::Rails::Server.new.stop
|
22
|
+
end
|
23
|
+
|
24
|
+
task :reindex => :"sunspot:reindex"
|
25
|
+
end
|
26
|
+
|
27
|
+
desc "Reindex all solr models that are located in your application's models directory."
|
28
|
+
# This task depends on the standard Rails file naming \
|
29
|
+
# conventions, in that the file name matches the defined class name. \
|
30
|
+
# By default the indexing system works in batches of 50 records, you can \
|
31
|
+
# set your own value for this by using the batch_size argument. You can \
|
32
|
+
# also optionally define a list of models to separated by a forward slash '/'
|
33
|
+
#
|
34
|
+
# $ rake sunspot:reindex # reindex all models
|
35
|
+
# $ rake sunspot:reindex[1000] # reindex in batches of 1000
|
36
|
+
# $ rake sunspot:reindex[false] # reindex without batching
|
37
|
+
# $ rake sunspot:reindex[,Post] # reindex only the Post model
|
38
|
+
# $ rake sunspot:reindex[1000,Post] # reindex only the Post model in
|
39
|
+
# # batchs of 1000
|
40
|
+
# $ rake sunspot:reindex[,Post+Author] # reindex Post and Author model
|
41
|
+
task :reindex, [:batch_size, :models] => [:environment] do |t, args|
|
42
|
+
reindex_options = {:batch_commit => false}
|
43
|
+
case args[:batch_size]
|
44
|
+
when 'false'
|
45
|
+
reindex_options[:batch_size] = nil
|
46
|
+
when /^\d+$/
|
47
|
+
reindex_options[:batch_size] = args[:batch_size].to_i if args[:batch_size].to_i > 0
|
48
|
+
end
|
49
|
+
unless args[:models]
|
50
|
+
models_path = Rails.root.join('app', 'models')
|
51
|
+
all_files = Dir.glob(models_path.join('**', '*.rb'))
|
52
|
+
all_models = all_files.map { |path| path.sub(models_path.to_s, '')[0..-4].camelize.sub(/^::/, '').constantize rescue nil }.compact
|
53
|
+
sunspot_models = all_models.select { |m| m < ActiveRecord::Base and m.searchable? }
|
54
|
+
else
|
55
|
+
sunspot_models = args[:models].split('+').map{|m| m.constantize}
|
56
|
+
end
|
57
|
+
sunspot_models.each do |model|
|
58
|
+
model.solr_reindex reindex_options
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'sunspot'
|
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')
|
6
|
+
|
7
|
+
module Sunspot #:nodoc:
|
8
|
+
module Rails #:nodoc:
|
9
|
+
autoload :SolrInstrumentation, File.join(File.dirname(__FILE__), 'rails', 'solr_instrumentation')
|
10
|
+
autoload :StubSessionProxy, File.join(File.dirname(__FILE__), 'rails', 'stub_session_proxy')
|
11
|
+
autoload :Server, File.join(File.dirname(__FILE__), 'rails', 'server')
|
12
|
+
autoload :VERSION, File.join(File.dirname(__FILE__), 'rails', 'version')
|
13
|
+
|
14
|
+
class <<self
|
15
|
+
attr_writer :configuration
|
16
|
+
|
17
|
+
def configuration
|
18
|
+
@configuration ||= Sunspot::Rails::Configuration.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def reset
|
22
|
+
@configuration = nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def build_session(configuration = self.configuration)
|
26
|
+
if configuration.has_master?
|
27
|
+
SessionProxy::MasterSlaveSessionProxy.new(
|
28
|
+
SessionProxy::ThreadLocalSessionProxy.new(master_config(configuration)),
|
29
|
+
SessionProxy::ThreadLocalSessionProxy.new(slave_config(configuration))
|
30
|
+
)
|
31
|
+
else
|
32
|
+
SessionProxy::ThreadLocalSessionProxy.new(slave_config(configuration))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def master_config(sunspot_rails_configuration)
|
39
|
+
config = Sunspot::Configuration.build
|
40
|
+
config.solr.url = URI::HTTP.build(
|
41
|
+
:host => sunspot_rails_configuration.master_hostname,
|
42
|
+
:port => sunspot_rails_configuration.master_port,
|
43
|
+
:path => sunspot_rails_configuration.master_path
|
44
|
+
).to_s
|
45
|
+
config
|
46
|
+
end
|
47
|
+
|
48
|
+
def slave_config(sunspot_rails_configuration)
|
49
|
+
config = Sunspot::Configuration.build
|
50
|
+
config.solr.url = URI::HTTP.build(
|
51
|
+
:host => sunspot_rails_configuration.hostname,
|
52
|
+
:port => sunspot_rails_configuration.port,
|
53
|
+
:path => sunspot_rails_configuration.path
|
54
|
+
).to_s
|
55
|
+
config
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# This needs to be loaded before sunspot/search/paginated_collection
|
2
|
+
# or #to_json gets defined in Object breaking delegation to Array via
|
3
|
+
# method_missing
|
4
|
+
require 'active_support/core_ext/object/to_json' if Rails::VERSION::MAJOR == 3
|
5
|
+
|
6
|
+
require 'sunspot/rails'
|
7
|
+
|
8
|
+
if Rails::VERSION::MAJOR == 3
|
9
|
+
require 'sunspot/rails/railtie'
|
10
|
+
else
|
11
|
+
require 'sunspot/rails/init'
|
12
|
+
end
|
@@ -0,0 +1,173 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe Sunspot::Rails::Configuration, "default values without a sunspot.yml" do
|
4
|
+
before(:each) do
|
5
|
+
File.stub!(:exist?).and_return(false) # simulate sunspot.yml not existing
|
6
|
+
@config = Sunspot::Rails::Configuration.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should handle the 'hostname' property when not set" do
|
10
|
+
@config.hostname.should == 'localhost'
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should handle the 'path' property when not set" do
|
14
|
+
@config.path.should == '/solr'
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "port" do
|
18
|
+
it "should default to port 8981 in test" do
|
19
|
+
::Rails.stub!(:env => 'test')
|
20
|
+
@config = Sunspot::Rails::Configuration.new
|
21
|
+
@config.port.should == 8981
|
22
|
+
end
|
23
|
+
it "should default to port 8982 in development" do
|
24
|
+
::Rails.stub!(:env => 'development')
|
25
|
+
@config = Sunspot::Rails::Configuration.new
|
26
|
+
@config.port.should == 8982
|
27
|
+
end
|
28
|
+
it "should default to 8983 in production" do
|
29
|
+
::Rails.stub!(:env => 'production')
|
30
|
+
@config = Sunspot::Rails::Configuration.new
|
31
|
+
@config.port.should == 8983
|
32
|
+
end
|
33
|
+
it "should generally default to 8983" do
|
34
|
+
::Rails.stub!(:env => 'staging')
|
35
|
+
@config = Sunspot::Rails::Configuration.new
|
36
|
+
@config.port.should == 8983
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should handle the 'log_level' property when not set" do
|
41
|
+
@config.log_level.should == 'INFO'
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should handle the 'log_file' property" do
|
45
|
+
@config.log_file.should =~ /log\/solr_test.log/
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should handle the 'solr_home' property when not set" do
|
49
|
+
Rails.should_receive(:root).at_least(1).and_return('/some/path')
|
50
|
+
@config.solr_home.should == '/some/path/solr'
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should handle the 'data_path' property when not set" do
|
54
|
+
Rails.should_receive(:root).at_least(1).and_return('/some/path')
|
55
|
+
@config.data_path.should == '/some/path/solr/data/test'
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should handle the 'pid_dir' property when not set" do
|
59
|
+
Rails.should_receive(:root).at_least(1).and_return('/some/path')
|
60
|
+
@config.pid_dir.should == '/some/path/solr/pids/test'
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should handle the 'auto_commit_after_request' propery when not set" do
|
64
|
+
@config.auto_commit_after_request?.should == true
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should handle the 'auto_commit_after_delete_request' propery when not set" do
|
68
|
+
@config.auto_commit_after_delete_request?.should == false
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe Sunspot::Rails::Configuration, "user provided sunspot.yml" do
|
73
|
+
before(:each) do
|
74
|
+
::Rails.stub!(:env => 'config_test')
|
75
|
+
@config = Sunspot::Rails::Configuration.new
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should handle the 'hostname' property when set" do
|
79
|
+
@config.hostname.should == 'some.host'
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should handle the 'port' property when set" do
|
83
|
+
@config.port.should == 1234
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should handle the 'path' property when set" do
|
87
|
+
@config.path.should == '/solr/idx'
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should handle the 'log_level' propery when set" do
|
91
|
+
@config.log_level.should == 'WARNING'
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should handle the 'solr_home' propery when set" do
|
95
|
+
@config.solr_home.should == '/my_superior_path'
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should handle the 'data_path' property when set" do
|
99
|
+
@config.data_path.should == '/my_superior_path/data'
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should handle the 'pid_dir' property when set" do
|
103
|
+
@config.pid_dir.should == '/my_superior_path/pids'
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should handle the 'solr_home' property when set" do
|
107
|
+
@config.solr_home.should == '/my_superior_path'
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should handle the 'auto_commit_after_request' propery when set" do
|
111
|
+
@config.auto_commit_after_request?.should == false
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should handle the 'auto_commit_after_delete_request' propery when set" do
|
115
|
+
@config.auto_commit_after_delete_request?.should == true
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
describe Sunspot::Rails::Configuration, "with ENV['SOLR_URL'] overriding sunspot.yml" do
|
121
|
+
before(:all) do
|
122
|
+
ENV['SOLR_URL'] = 'http://environment.host:5432/solr/env'
|
123
|
+
end
|
124
|
+
|
125
|
+
before(:each) do
|
126
|
+
::Rails.stub!(:env => 'config_test')
|
127
|
+
@config = Sunspot::Rails::Configuration.new
|
128
|
+
end
|
129
|
+
|
130
|
+
after(:all) do
|
131
|
+
ENV.delete('SOLR_URL')
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should handle the 'hostname' property when set" do
|
135
|
+
@config.hostname.should == 'environment.host'
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should handle the 'port' property when set" do
|
139
|
+
@config.port.should == 5432
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should handle the 'path' property when set" do
|
143
|
+
@config.path.should == '/solr/env'
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe Sunspot::Rails::Configuration, "with ENV['WEBSOLR_URL'] overriding sunspot.yml" do
|
148
|
+
before(:all) do
|
149
|
+
ENV['WEBSOLR_URL'] = 'http://index.websolr.test/solr/a1b2c3d4e5f'
|
150
|
+
end
|
151
|
+
|
152
|
+
before(:each) do
|
153
|
+
::Rails.stub!(:env => 'config_test')
|
154
|
+
@config = Sunspot::Rails::Configuration.new
|
155
|
+
end
|
156
|
+
|
157
|
+
after(:all) do
|
158
|
+
ENV.delete('WEBSOLR_URL')
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should handle the 'hostname' property when set" do
|
162
|
+
@config.hostname.should == 'index.websolr.test'
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should handle the 'port' property when set" do
|
166
|
+
@config.port.should == 80
|
167
|
+
end
|
168
|
+
|
169
|
+
it "should handle the 'path' property when set" do
|
170
|
+
@config.path.should == '/solr/a1b2c3d4e5f'
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe 'searchable with lifecycle' do
|
4
|
+
describe 'on create' do
|
5
|
+
before :each do
|
6
|
+
@post = PostWithAuto.create
|
7
|
+
Sunspot.commit
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should automatically index' do
|
11
|
+
PostWithAuto.search.results.should == [@post]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'on update' do
|
16
|
+
before :each do
|
17
|
+
@post = PostWithAuto.create
|
18
|
+
@post.update_attributes(:title => 'Test 1')
|
19
|
+
Sunspot.commit
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should automatically update index' do
|
23
|
+
PostWithAuto.search { with :title, 'Test 1' }.results.should == [@post]
|
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 :solr_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 :solr_index
|
37
|
+
@post.save!
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe 'on destroy' do
|
42
|
+
before :each do
|
43
|
+
@post = PostWithAuto.create
|
44
|
+
@post.destroy
|
45
|
+
Sunspot.commit
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should automatically remove it from the index' do
|
49
|
+
PostWithAuto.search_ids.should be_empty
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe 'searchable with lifecycle - ignoring specific attributes' do
|
55
|
+
before(:each) do
|
56
|
+
@post = PostWithAuto.create
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should not reindex the object on an update_at change, because it is marked as to-ignore" do
|
60
|
+
Sunspot.should_not_receive(:index).with(@post)
|
61
|
+
@post.update_attribute :updated_at, 123.seconds.from_now
|
62
|
+
end
|
63
|
+
end
|