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.
data/History.txt CHANGED
@@ -1,3 +1,15 @@
1
+ == 1.0.0
2
+ * Sunspot::Rails::Server subclasses Sunspot::Server; no longer needs to shell out
3
+ * Use Sunspot built-in session proxies in Sunspot::Rails
4
+ * Sunspot::Rails adapter compatible with assumed inconsistency
5
+ * Use session proxy for disconnecting Sunspot in specs
6
+ * Allow specification of first ID for reindex batches.
7
+ * Log Solr requests in Rails logger
8
+ * Use class_inheritable_hash for sunspot_options
9
+ * Add `index` class method, which is like `reindex` but doesn't clear first
10
+ * Rename sunspot:solr:reindex to sunspot:reindex
11
+ * Use Sunspot::Installer to bootstrap Rails Solr home
12
+
1
13
  == 0.10.7
2
14
  * Added Sunspot::Rails::Server class to start/stop/run/bootstrap the solr server
3
15
  * Added log_level key to sunspot.yml, see java docs for valid values (http://java.sun.com/j2se/1.5.0/docs/api/java/util/logging/Level.html)
data/README.rdoc CHANGED
@@ -206,31 +206,24 @@ used as intended.
206
206
 
207
207
  == Testing Solr integration using RSpec
208
208
 
209
- To disable the sunspot-solr integration for your active record models, add the
210
- following line to your spec_helper.rb
209
+ To disable the sunspot-solr integration for your active record models, require
210
+ the file `sunspot/rails/spec_helper`
211
211
 
212
- require 'sunspot/spec/extension'
212
+ Then, in your spec, use the #disconnect_sunspot method:
213
213
 
214
- This will disable all automatic after_save/after_destroy solr-requests generated
215
- via the #searchable method. This will not disable/mock explicit calls in your code.
214
+ require 'sunspot/rails/spec_helper'
216
215
 
217
- If you want to test the sunspot-solr integration with active record, you can
218
- reenable the after_save/after_destroy hooks by adding 'integrate_sunspot' in your
219
- examples.
220
-
221
- describe Searches do
222
- integrate_sunspot
223
-
224
- before(:each) do
225
- @movie = Factory.create :movie
226
- end
216
+ describe Post do
217
+ disconnect_sunspot
227
218
 
228
- it "should find a movie" do
229
- Movie.search { keywords @movie.title }.first.should == @movie
219
+ it 'should have some behavior'
220
+ # ...
230
221
  end
231
222
  end
232
223
 
233
-
224
+ In all of the examples in this group, all Sunspot calls will be stubbed out. The
225
+ Sunspot#search method will return a stub search object that mimics a search with
226
+ no results.
234
227
 
235
228
  == Further Reading
236
229
 
@@ -254,6 +247,7 @@ http://outoftime.lighthouseapp.com/projects/20339-sunspot
254
247
  - Benjamin Krause (bk@benjaminkrause.com)
255
248
  - Adam Salter (adam@codebright.net)
256
249
  - Brandon Keepers (brandon@opensoul.org)
250
+ - Paul Canavese (paul@canavese.org)
257
251
 
258
252
  == License
259
253
 
data/TODO CHANGED
@@ -1,4 +1,4 @@
1
- * Session proxy should give access to config
1
+ * Delegate new_search method
2
2
  =======
3
3
  * Fix final status output for reindex
4
4
  * Add batch-per-request option
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :patch: 4
3
+ :major: 0
4
+ :minor: 11
@@ -1,7 +1,8 @@
1
- require File.join(File.dirname(__FILE__), '..', '..', 'sunspot', 'lib', 'sunspot', 'gem_tasks')
2
- require File.join(File.dirname(__FILE__), '..', 'lib', 'sunspot', 'rails', 'version')
1
+ require File.join(File.dirname(__FILE__), '..', '..', 'tools', 'gem_tasks')
3
2
 
4
3
  Sunspot::GemTasks.new do |s|
4
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'sunspot', 'rails', 'version')
5
+
5
6
  s.name = 'sunspot_rails'
6
7
  s.version = Sunspot::Rails::VERSION
7
8
  s.summary = 'Rails integration for the Sunspot Solr search library'
@@ -15,21 +16,19 @@ running a Sunspot-compatible Solr instance for development and test
15
16
  environments, and automatically commit Solr index changes at the end of each
16
17
  Rails request.
17
18
  TEXT
18
- s.authors = ['Mat Brown', 'Peer Allan', 'Michael Moen', 'Benjamin Krause']
19
+ s.authors = ['Mat Brown', 'Peer Allan', 'Michael Moen', 'Benjamin Krause', 'Adam Salter', 'Brandon Keepers', 'Paul Canavese']
19
20
  s.rubyforge_project = 'sunspot'
20
21
  s.files = FileList['[A-Z]*',
21
- '{lib,tasks,dev_tasks}/**/*',
22
- 'generators/**/*',
23
- 'install.rb',
24
- 'MIT-LICENSE',
25
- 'rails/*',
26
- 'spec/*.rb',
27
- 'spec/mock_app/{app,lib,db,vendor,config}/**/*',
28
- 'spec/mock_app/{tmp,log,solr}']
22
+ '{lib,tasks,dev_tasks}/**/*',
23
+ 'generators/**/*',
24
+ 'install.rb',
25
+ 'MIT-LICENSE',
26
+ 'rails/*',
27
+ 'spec/*.rb',
28
+ 'spec/mock_app/{app,lib,db,vendor,config}/**/*',
29
+ 'spec/mock_app/{tmp,log,solr}']
29
30
  s.add_dependency 'escape', '>= 0.0.4'
30
- s.add_dependency 'sunspot', '>= 0.10.6', '<= 0.10.8'
31
+ s.add_dependency 'sunspot', Sunspot::Rails::VERSION
31
32
  s.add_development_dependency 'rspec', '~> 1.2'
32
33
  s.add_development_dependency 'rspec-rails', '~> 1.2'
33
- s.add_development_dependency 'ruby-debug', '~> 0.10'
34
- s.add_development_dependency 'technicalpickles-jeweler', '~> 1.0'
35
34
  end
@@ -47,7 +47,7 @@ module Sunspot #:nodoc:
47
47
  # ActiveRecord::Base:: ActiveRecord model
48
48
  #
49
49
  def load(id)
50
- @clazz.find(id.to_i, options_for_find)
50
+ @clazz.find_by_id(id.to_i, options_for_find)
51
51
  end
52
52
 
53
53
  #
@@ -62,7 +62,7 @@ module Sunspot #:nodoc:
62
62
  # Array:: Collection of ActiveRecord models
63
63
  #
64
64
  def load_all(ids)
65
- @clazz.find(ids.map { |id| id.to_i }, options_for_find)
65
+ @clazz.find_all_by_id(ids.map { |id| id.to_i }, options_for_find)
66
66
  end
67
67
 
68
68
  private
@@ -36,7 +36,7 @@ module Sunspot #:nodoc:
36
36
  # </b>(see the README).
37
37
  # :ignore_attribute_changes_of<Array>::
38
38
  # Define attributes, that should not trigger a reindex of that
39
- # object. Usual suspects are update_at or counters.
39
+ # object. Usual suspects are updated_at or counters.
40
40
  #
41
41
  # ==== Example
42
42
  #
@@ -57,13 +57,12 @@ module Sunspot #:nodoc:
57
57
  unless searchable?
58
58
  extend ClassMethods
59
59
  include InstanceMethods
60
-
61
- Sunspot::Rails::Util.sunspot_options[self.to_s.underscore.to_sym] = options
60
+
61
+ class_inheritable_hash :sunspot_options
62
62
 
63
63
  unless options[:auto_index] == false
64
- after_save do |searchable|
65
- searchable.index if Sunspot::Rails::Util.index_relevant_attribute_changed?( searchable )
66
- end
64
+ before_save :maybe_mark_for_auto_indexing
65
+ after_save :maybe_auto_index
67
66
  end
68
67
 
69
68
  unless options[:auto_remove] == false
@@ -72,6 +71,7 @@ module Sunspot #:nodoc:
72
71
  end
73
72
  end
74
73
  end
74
+ self.sunspot_options = options
75
75
  end
76
76
 
77
77
  #
@@ -137,17 +137,24 @@ module Sunspot #:nodoc:
137
137
  # Remove all instances of this class from the Solr index and immediately
138
138
  # commit.
139
139
  #
140
- #---
141
- # XXX Sunspot should implement remove_all!()
142
140
  #
143
141
  def remove_all_from_index!
144
- remove_all_from_index
145
- Sunspot.commit
142
+ Sunspot.remove_all!(self)
146
143
  end
147
144
 
148
145
  #
149
146
  # Completely rebuild the index for this class. First removes all
150
- # instances from the index, then loads records and save them. The
147
+ # instances from the index, then loads records and indexes them.
148
+ #
149
+ # See #index for information on options, etc.
150
+ #
151
+ def reindex(options = {})
152
+ remove_all_from_index
153
+ index(options)
154
+ end
155
+
156
+ #
157
+ # Add/update all existing records in the Solr index. The
151
158
  # +batch_size+ argument specifies how many records to load out of the
152
159
  # database at a time. The default batch size is 500; if nil is passed,
153
160
  # records will not be indexed in batches. By default, a commit is issued
@@ -166,31 +173,33 @@ module Sunspot #:nodoc:
166
173
  # used for including associated objects that need to be
167
174
  # indexed with the parent object, accepts all formats
168
175
  # ActiveRecord::Base.find does
176
+ # first_id:: The lowest possible ID for this class. Defaults to 0, which
177
+ # is fine for integer IDs; string primary keys will need to
178
+ # specify something reasonable here.
169
179
  #
170
180
  # ==== Examples
171
181
  #
172
- # # reindex in batches of 500, commit after each
173
- # Post.reindex
182
+ # # index in batches of 500, commit after each
183
+ # Post.index
174
184
  #
175
185
  # # index all rows at once, then commit
176
- # Post.reindex(:batch_size => nil)
186
+ # Post.index(:batch_size => nil)
177
187
  #
178
- # # reindex in batches of 500, commit when all batches complete
179
- # Post.reindex(:batch_commit => false)
188
+ # # index in batches of 500, commit when all batches complete
189
+ # Post.index(:batch_commit => false)
180
190
  #
181
191
  # # include the associated +author+ object when loading to index
182
- # Post.reindex(:include => :author)
192
+ # Post.index(:include => :author)
183
193
  #
184
- def reindex(opts={})
185
- options = { :batch_size => 500, :batch_commit => true, :include => []}.merge(opts)
186
- remove_all_from_index
194
+ def index(opts={})
195
+ options = { :batch_size => 500, :batch_commit => true, :include => [], :first_id => 0}.merge(opts)
187
196
  unless options[:batch_size]
188
197
  Sunspot.index!(all(:include => options[:include]))
189
198
  else
190
199
  offset = 0
191
200
  counter = 1
192
201
  record_count = count
193
- last_id = 0
202
+ last_id = options[:first_id]
194
203
  while(offset < record_count)
195
204
  benchmark options[:batch_size], counter do
196
205
  records = all(:include => options[:include], :conditions => ["#{table_name}.#{primary_key} > ?", last_id], :limit => options[:batch_size], :order => primary_key)
@@ -303,6 +312,25 @@ module Sunspot #:nodoc:
303
312
  def remove_from_index!
304
313
  Sunspot.remove!(self)
305
314
  end
315
+
316
+ private
317
+
318
+ def maybe_mark_for_auto_indexing
319
+ @marked_for_auto_indexing =
320
+ if !new_record? && ignore_attributes = self.class.sunspot_options[:ignore_attribute_changes_of]
321
+ @marked_for_auto_indexing = !(changed.map { |attr| attr.to_sym } - ignore_attributes).blank?
322
+ else
323
+ true
324
+ end
325
+ true
326
+ end
327
+
328
+ def maybe_auto_index
329
+ if @marked_for_auto_indexing
330
+ index
331
+ remove_instance_variable(:@marked_for_auto_indexing)
332
+ end
333
+ end
306
334
  end
307
335
  end
308
336
  end
@@ -1,229 +1,152 @@
1
- require 'escape'
2
-
3
- module Sunspot #:nodoc:
4
- module Rails #:nodoc:
5
- # The Sunspot::Rails::Server class is a simple wrapper around
6
- # the start/stop scripts for solr.
7
- class Server
8
-
9
- class << self
10
- delegate :log_file, :log_level, :port, :solr_home, :to => :configuration
11
-
12
- # Name of the sunspot executable (shell script)
13
- SUNSPOT_EXECUTABLE = (RUBY_PLATFORM =~ /w(in)?32$/ ? 'sunspot-solr.bat' : 'sunspot-solr')
14
-
15
- #
16
- # Start the sunspot-solr server. Bootstrap solr_home first,
17
- # if neccessary.
18
- #
19
- # ==== Returns
20
- #
21
- # Boolean:: success
22
- #
23
- def start
24
- bootstrap if bootstrap_neccessary?
25
- execute( start_command )
26
- end
27
-
28
- #
29
- # Run the sunspot-solr server in the foreground. Boostrap
30
- # solr_home first, if neccessary.
31
- #
32
- # ==== Returns
33
- #
34
- # Boolean:: success
35
- #
36
- def run
37
- bootstrap if bootstrap_neccessary?
38
- execute( run_command )
39
- end
40
-
41
- #
42
- # Stop the sunspot-solr server.
43
- #
44
- # ==== Returns
45
- #
46
- # Boolean:: success
47
- #
48
- def stop
49
- execute( stop_command )
50
- end
51
-
52
- #
53
- # Directory to store solr config files
54
- #
55
- # ==== Returns
56
- #
57
- # String:: config_path
58
- #
59
- def config_path
60
- File.join( solr_home, 'conf' )
61
- end
62
-
63
- #
64
- # Directory to store lucene index data files
65
- #
66
- # ==== Returns
67
- #
68
- # String:: data_path
69
- #
70
- def data_path
71
- File.join( solr_home, 'data', ::Rails.env )
72
- end
1
+ module Sunspot
2
+ module Rails
3
+ class Server < Sunspot::Server
4
+ # ActiveSupport log levels are integers; this array maps them to the
5
+ # appropriate java.util.logging.Level constant
6
+ LOG_LEVELS = %w(FINE INFO WARNING SEVERE SEVERE INFO)
73
7
 
74
- #
75
- # Directory to store custom libraries for solr
76
- #
77
- # ==== Returns
78
- #
79
- # String:: lib_path
80
- #
81
- def lib_path
82
- File.join( solr_home, 'lib' )
83
- end
84
-
85
- #
86
- # Directory to store pid files
87
- #
88
- # ==== Returns
89
- #
90
- # String:: pid_path
91
- #
92
- def pid_path
93
- File.join( solr_home, 'pids', ::Rails.env )
94
- end
95
-
96
- #
97
- # Bootstrap a new solr_home by creating all required
98
- # directories.
99
- #
100
- # ==== Returns
101
- #
102
- # Boolean:: success
103
- #
104
- def bootstrap
105
- create_solr_directories and create_solr_configuration_files and copy_custom_solr_libraries
106
- end
107
-
108
- #
109
- # Check for bootstrap necessity
110
- #
111
- # ==== Returns
112
- #
113
- # Boolean:: neccessary
114
- #
115
- def bootstrap_neccessary?
116
- !File.directory?( solr_home ) or !File.exists?( File.join( config_path, 'solrconfig.xml' ) )
117
- end
118
-
119
-
120
- protected
121
-
122
- #
123
- # Generate the start command for the sunspot-solr executable
124
- #
125
- # ==== Returns
126
- #
127
- # Array:: sunspot_start_command
128
- #
129
- def start_command
130
- [ SUNSPOT_EXECUTABLE, 'start', '-p', port.to_s, '-d', data_path, '-s', solr_home, '-l', log_level, '--log-file', log_file ]
131
- end
8
+ def start
9
+ bootstrap
10
+ super
11
+ end
132
12
 
133
- #
134
- # Generate the stop command for the sunspot-solr executable
135
- #
136
- # ==== Returns
137
- #
138
- # Array:: sunspot_stop_command
139
- #
140
- def stop_command
141
- [ SUNSPOT_EXECUTABLE, 'stop' ]
142
- end
13
+ def run
14
+ bootstrap
15
+ super
16
+ end
143
17
 
144
- #
145
- # Generate the run command for the sunspot-solr executable
146
- #
147
- # ==== Returns
148
- #
149
- # Array:: run_command
150
- #
151
- def run_command
152
- [ SUNSPOT_EXECUTABLE, 'run', '-p', port.to_s, '-d', data_path, '-s', solr_home, '-l', log_level, '-lf', log_file ]
153
- end
154
-
155
- #
156
- # access to the Sunspot::Rails::Configuration, defined in
157
- # sunspot.yml. Use Sunspot::Rails.configuration if you want
158
- # to access the configuration directly.
159
- #
160
- # ==== returns
161
- #
162
- # Sunspot::Rails::Configuration:: configuration
163
- #
164
- def configuration
165
- Sunspot::Rails.configuration
166
- end
167
-
168
- private
169
-
170
- #
171
- # Change directory to the pid file path and execute a
172
- # command on a subshell.
173
- #
174
- # ==== Returns
175
- #
176
- # Boolean:: success
177
- #
178
- def execute( command )
179
- success = false
180
- FileUtils.cd( pid_path ) do
181
- success = Kernel.system(Escape.shell_command( command ))
182
- end
183
- success
184
- end
185
-
186
- #
187
- # Create new solr_home, config, log and pid directories
188
- #
189
- # ==== Returns
190
- #
191
- # Boolean:: success
192
- #
193
- def create_solr_directories
194
- [ solr_home, config_path, data_path, pid_path, lib_path ].each do |path|
195
- FileUtils.mkdir_p( path )
196
- end
18
+ #
19
+ # Bootstrap a new solr_home by creating all required
20
+ # directories.
21
+ #
22
+ # ==== Returns
23
+ #
24
+ # Boolean:: success
25
+ #
26
+ def bootstrap
27
+ unless @bootstrapped
28
+ install_solr_home
29
+ @bootstrapped = true
197
30
  end
198
-
199
- #
200
- # Copy custom solr libraries (like localsolr) to the
201
- # lib directory
202
- #
203
- # ==== Returns
204
- #
205
- # Boolean:: success
206
- #
207
- def copy_custom_solr_libraries
208
- Dir.glob( File.join( Sunspot::Configuration.solr_default_configuration_location, '..', 'lib', '*.jar') ).each do |jar_file|
209
- FileUtils.cp( jar_file, lib_path )
210
- end
31
+ end
32
+
33
+ #
34
+ # Directory to store custom libraries for solr
35
+ #
36
+ def lib_path
37
+ File.join( solr_home, 'lib' )
38
+ end
39
+
40
+ #
41
+ # Directory in which to store PID files
42
+ #
43
+ def pid_dir
44
+ File.join(::Rails.root, 'tmp', 'pids')
45
+ end
46
+
47
+ #
48
+ # Name of the PID file
49
+ #
50
+ def pid_file
51
+ "sunspot-solr-#{::Rails.env}.pid"
52
+ end
53
+
54
+ #
55
+ # Directory to store lucene index data files
56
+ #
57
+ # ==== Returns
58
+ #
59
+ # String:: data_path
60
+ #
61
+ def solr_data_dir
62
+ File.join(solr_home, 'data', ::Rails.env)
63
+ end
64
+
65
+ #
66
+ # Directory to use for Solr home.
67
+ #
68
+ def solr_home
69
+ File.join(::Rails.root, 'solr')
70
+ end
71
+
72
+ #
73
+ # Port on which to run Solr
74
+ #
75
+ def port
76
+ configuration.port
77
+ end
78
+
79
+ #
80
+ # Severity level for logging. This is based on the severity level for the
81
+ # Rails logger.
82
+ #
83
+ def log_level
84
+ LOG_LEVELS[::Rails.logger.level]
85
+ end
86
+
87
+ #
88
+ # Log file for Solr. File is in the rails log/ directory.
89
+ #
90
+ def log_file
91
+ File.join(::Rails.root, 'log', "sunspot-solr-#{::Rails.env}.log")
92
+ end
93
+
94
+ private
95
+
96
+ #
97
+ # access to the Sunspot::Rails::Configuration, defined in
98
+ # sunspot.yml. Use Sunspot::Rails.configuration if you want
99
+ # to access the configuration directly.
100
+ #
101
+ # ==== returns
102
+ #
103
+ # Sunspot::Rails::Configuration:: configuration
104
+ #
105
+ def configuration
106
+ Sunspot::Rails.configuration
107
+ end
108
+
109
+ #
110
+ # Directory to store solr config files
111
+ #
112
+ # ==== Returns
113
+ #
114
+ # String:: config_path
115
+ #
116
+ def config_path
117
+ File.join(solr_home, 'conf')
118
+ end
119
+
120
+ #
121
+ # Copy default solr configuration files from sunspot
122
+ # gem to the new solr_home/config directory
123
+ #
124
+ # ==== Returns
125
+ #
126
+ # Boolean:: success
127
+ #
128
+ def install_solr_home
129
+ unless File.exists?(solr_home)
130
+ Sunspot::Installer.execute(
131
+ solr_home,
132
+ :force => true,
133
+ :verbose => true
134
+ )
211
135
  end
212
-
213
- #
214
- # Copy default solr configuration files from sunspot
215
- # gem to the new solr_home/config directory
216
- #
217
- # ==== Returns
218
- #
219
- # Boolean:: success
220
- #
221
- def create_solr_configuration_files
222
- Dir.glob( File.join( Sunspot::Configuration.solr_default_configuration_location, '*') ).each do |config_file|
223
- FileUtils.cp( config_file, config_path )
224
- end
136
+ end
137
+
138
+ #
139
+ # Create new solr_home, config, log and pid directories
140
+ #
141
+ # ==== Returns
142
+ #
143
+ # Boolean:: success
144
+ #
145
+ def create_solr_directories
146
+ [solr_data_dir, pid_dir].each do |path|
147
+ FileUtils.mkdir_p( path )
225
148
  end
226
149
  end
227
150
  end
228
151
  end
229
- end
152
+ end