sunspot_rails 0.10.9 → 0.11.0

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