sunspot_rails 0.10.9 → 0.11.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.
@@ -9,7 +9,11 @@ module Sunspot #:nodoc:
9
9
  class <<self
10
10
  def included(base) #:nodoc:
11
11
  base.after_filter do
12
- Sunspot.commit_if_dirty if Sunspot::Rails.configuration.auto_commit_after_request?
12
+ if Sunspot::Rails.configuration.auto_commit_after_request?
13
+ Sunspot.commit_if_dirty
14
+ elsif Sunspot::Rails.configuration.auto_commit_after_delete_request?
15
+ Sunspot.commit_if_delete_dirty
16
+ end
13
17
  end
14
18
  end
15
19
  end
@@ -34,6 +34,9 @@ module Sunspot #:nodoc:
34
34
  # Automatically remove models from the Solr index when they are
35
35
  # destroyed. <b>Setting this option to +false+ is not recommended
36
36
  # </b>(see the README).
37
+ # :ignore_attribute_changes_of<Array>::
38
+ # Define attributes, that should not trigger a reindex of that
39
+ # object. Usual suspects are update_at or counters.
37
40
  #
38
41
  # ==== Example
39
42
  #
@@ -54,10 +57,12 @@ module Sunspot #:nodoc:
54
57
  unless searchable?
55
58
  extend ClassMethods
56
59
  include InstanceMethods
57
-
60
+
61
+ Sunspot::Rails::Util.sunspot_options[self.to_s.underscore.to_sym] = options
62
+
58
63
  unless options[:auto_index] == false
59
64
  after_save do |searchable|
60
- searchable.index
65
+ searchable.index if Sunspot::Rails::Util.index_relevant_attribute_changed?( searchable )
61
66
  end
62
67
  end
63
68
 
@@ -136,7 +141,7 @@ module Sunspot #:nodoc:
136
141
  # XXX Sunspot should implement remove_all!()
137
142
  #
138
143
  def remove_all_from_index!
139
- Sunspot.remove_all(self)
144
+ remove_all_from_index
140
145
  Sunspot.commit
141
146
  end
142
147
 
@@ -182,12 +187,15 @@ module Sunspot #:nodoc:
182
187
  unless options[:batch_size]
183
188
  Sunspot.index!(all(:include => options[:include]))
184
189
  else
185
- record_count = count
186
- counter = 1
187
190
  offset = 0
191
+ counter = 1
192
+ record_count = count
193
+ last_id = 0
188
194
  while(offset < record_count)
189
195
  benchmark options[:batch_size], counter do
190
- Sunspot.index(all(:include => options[:include], :offset => offset, :limit => options[:batch_size], :order => primary_key))
196
+ records = all(:include => options[:include], :conditions => ["#{table_name}.#{primary_key} > ?", last_id], :limit => options[:batch_size], :order => primary_key)
197
+ Sunspot.index(records)
198
+ last_id = records.last.id
191
199
  end
192
200
  Sunspot.commit if options[:batch_commit]
193
201
  offset += options[:batch_size]
@@ -292,12 +300,8 @@ module Sunspot #:nodoc:
292
300
  # Remove the model from the Solr index and commit immediately. See
293
301
  # #remove_from_index
294
302
  #
295
- #---
296
- #FIXME Sunspot should implement remove!()
297
- #
298
303
  def remove_from_index!
299
- Sunspot.remove(self)
300
- Sunspot.commit
304
+ Sunspot.remove!(self)
301
305
  end
302
306
  end
303
307
  end
@@ -0,0 +1,229 @@
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
73
+
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
132
+
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
143
+
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
197
+ 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
211
+ 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
225
+ end
226
+ end
227
+ end
228
+ end
229
+ end
@@ -0,0 +1,62 @@
1
+ module Sunspot
2
+ module Rails
3
+ class SessionProxy
4
+ extend MonitorMixin
5
+
6
+ class <<self
7
+ def instance
8
+ synchronize do
9
+ @instance ||= new
10
+ end
11
+ end
12
+
13
+ def reset!
14
+ synchronize do
15
+ @instance = nil
16
+ end
17
+ end
18
+
19
+ private :new
20
+ end
21
+
22
+ delegate :new_search, :search, :to => :read_session
23
+ delegate :index, :index!, :commit, :remove, :remove!, :remove_by_id,
24
+ :remove_by_id!, :remove_all, :remove_all!, :dirty?, :commit_if_dirty, :batch,
25
+ :to => :write_session
26
+
27
+ def initialize
28
+ @configuration = Sunspot::Rails::Configuration.new
29
+ end
30
+
31
+ private
32
+
33
+ def read_session
34
+ Thread.current[:sunspot_rails_read_session] ||=
35
+ begin
36
+ session = Sunspot::Session.new
37
+ session.config.solr.url = URI::HTTP.build(
38
+ :host => @configuration.hostname,
39
+ :port => @configuration.port,
40
+ :path => @configuration.path
41
+ ).to_s
42
+ session
43
+ end
44
+ end
45
+
46
+ def write_session
47
+ Thread.current[:sunspot_rails_write_session] ||=
48
+ if @configuration.has_master?
49
+ master_session = Sunspot::Session.new
50
+ master_session.config.solr.url = URI::HTTP.build(
51
+ :host => configuration.master_hostname,
52
+ :port => configuration.master_port,
53
+ :path => configuration.master_path
54
+ ).to_s
55
+ master_session
56
+ else
57
+ read_session
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -1,5 +1,3 @@
1
- require 'escape'
2
-
3
1
  namespace :sunspot do
4
2
  namespace :solr do
5
3
  desc 'Start the Solr instance'
@@ -7,47 +5,31 @@ namespace :sunspot do
7
5
  if RUBY_PLATFORM =~ /w(in)?32$/
8
6
  abort('This command does not work on Windows. Please use rake sunspot:solr:run to run Solr in the foreground.')
9
7
  end
10
- data_path = File.join(::Rails.root, 'solr', 'data', ::Rails.env)
11
- pid_path = File.join(::Rails.root, 'solr', 'pids', ::Rails.env)
12
- solr_home =
13
- if %w(solrconfig schema).all? { |file| File.exist?(File.join(::Rails.root, 'solr', 'conf', "#{file}.xml")) }
14
- File.join(::Rails.root, 'solr')
15
- end
16
- [data_path, pid_path].each { |path| FileUtils.mkdir_p(path) }
17
- port = Sunspot::Rails.configuration.port
18
- FileUtils.cd(File.join(pid_path)) do
19
- command = ['sunspot-solr', 'start', '-p', port.to_s, '-d', data_path]
20
- if solr_home
21
- command << '-s' << solr_home
22
- end
23
- system(Escape.shell_command(command))
24
- end
8
+ Sunspot::Rails::Server.start
25
9
  end
26
10
 
27
11
  desc 'Run the Solr instance in the foreground'
28
12
  task :run => :environment do
29
- data_path = File.join(::Rails.root, 'solr', 'data', ::Rails.env)
30
- solr_home =
31
- if %w(solrconfig schema).all? { |file| File.exist?(File.join(::Rails.root, 'solr', 'conf', "#{file}.xml")) }
32
- File.join(::Rails.root, 'solr')
33
- end
34
- FileUtils.mkdir_p(data_path)
35
- port = Sunspot::Rails.configuration.port
36
- command = ['sunspot-solr', 'run', '-p', port.to_s, '-d', data_path]
37
- if RUBY_PLATFORM =~ /w(in)?32$/
38
- command.first << '.bat'
39
- end
40
- if solr_home
41
- command << '-s' << solr_home
42
- end
43
- exec(Escape.shell_command(command))
13
+ Sunspot::Rails::Server.run
44
14
  end
45
15
 
46
16
  desc 'Stop the Solr instance'
47
17
  task :stop => :environment do
48
- FileUtils.cd(File.join(::Rails.root, 'solr', 'pids', ::Rails.env)) do
49
- system(Escape.shell_command(['sunspot-solr', 'stop']))
18
+ if RUBY_PLATFORM =~ /w(in)?32$/
19
+ abort('This command does not work on Windows.')
20
+ end
21
+ Sunspot::Rails::Server.stop
22
+ end
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
50
32
  end
51
33
  end
52
34
  end
53
- end
35
+ end
@@ -0,0 +1,20 @@
1
+ require 'escape'
2
+
3
+ module Sunspot #:nodoc:
4
+ module Rails #:nodoc:
5
+ class Util
6
+ class << self
7
+ def sunspot_options
8
+ @sunspot_options ||= {}
9
+ end
10
+
11
+ def index_relevant_attribute_changed?( object )
12
+ class_key = object.class.to_s.underscore.to_sym
13
+ ignore_attributes = (sunspot_options[class_key][:ignore_attribute_changes_of] || [])
14
+ !(object.changes.symbolize_keys.keys - ignore_attributes).blank?
15
+ end
16
+
17
+ end
18
+ end
19
+ end
20
+ end