robsharp-sunspot_rails 1.1.0.2

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.
Files changed (55) hide show
  1. data/History.txt +40 -0
  2. data/LICENSE +18 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +256 -0
  5. data/Rakefile +27 -0
  6. data/TODO +8 -0
  7. data/VERSION.yml +4 -0
  8. data/dev_tasks/gemspec.rake +33 -0
  9. data/dev_tasks/rdoc.rake +24 -0
  10. data/dev_tasks/release.rake +4 -0
  11. data/dev_tasks/todo.rake +4 -0
  12. data/generators/sunspot/sunspot_generator.rb +9 -0
  13. data/generators/sunspot/templates/sunspot.yml +18 -0
  14. data/install.rb +1 -0
  15. data/lib/sunspot/rails.rb +58 -0
  16. data/lib/sunspot/rails/adapters.rb +160 -0
  17. data/lib/sunspot/rails/configuration.rb +272 -0
  18. data/lib/sunspot/rails/request_lifecycle.rb +31 -0
  19. data/lib/sunspot/rails/searchable.rb +464 -0
  20. data/lib/sunspot/rails/server.rb +173 -0
  21. data/lib/sunspot/rails/solr_logging.rb +58 -0
  22. data/lib/sunspot/rails/spec_helper.rb +19 -0
  23. data/lib/sunspot/rails/stub_session_proxy.rb +88 -0
  24. data/lib/sunspot/rails/tasks.rb +62 -0
  25. data/lib/sunspot/rails/version.rb +5 -0
  26. data/rails/init.rb +10 -0
  27. data/spec/configuration_spec.rb +102 -0
  28. data/spec/mock_app/app/controllers/application.rb +10 -0
  29. data/spec/mock_app/app/controllers/application_controller.rb +10 -0
  30. data/spec/mock_app/app/controllers/posts_controller.rb +6 -0
  31. data/spec/mock_app/app/models/author.rb +8 -0
  32. data/spec/mock_app/app/models/blog.rb +12 -0
  33. data/spec/mock_app/app/models/location.rb +2 -0
  34. data/spec/mock_app/app/models/photo_post.rb +2 -0
  35. data/spec/mock_app/app/models/post.rb +10 -0
  36. data/spec/mock_app/app/models/post_with_auto.rb +10 -0
  37. data/spec/mock_app/config/boot.rb +110 -0
  38. data/spec/mock_app/config/database.yml +4 -0
  39. data/spec/mock_app/config/environment.rb +42 -0
  40. data/spec/mock_app/config/environments/development.rb +27 -0
  41. data/spec/mock_app/config/environments/test.rb +27 -0
  42. data/spec/mock_app/config/initializers/new_rails_defaults.rb +19 -0
  43. data/spec/mock_app/config/initializers/session_store.rb +15 -0
  44. data/spec/mock_app/config/routes.rb +43 -0
  45. data/spec/mock_app/config/sunspot.yml +19 -0
  46. data/spec/mock_app/db/schema.rb +27 -0
  47. data/spec/model_lifecycle_spec.rb +63 -0
  48. data/spec/model_spec.rb +409 -0
  49. data/spec/request_lifecycle_spec.rb +52 -0
  50. data/spec/schema.rb +27 -0
  51. data/spec/server_spec.rb +36 -0
  52. data/spec/session_spec.rb +24 -0
  53. data/spec/spec_helper.rb +51 -0
  54. data/spec/stub_session_proxy_spec.rb +122 -0
  55. metadata +170 -0
@@ -0,0 +1,4 @@
1
+ desc 'Show all TODO and related tags'
2
+ task :todo do
3
+ FileList['lib/**/*.rb'].egrep(/#.*(TODO|FIXME|XXX)/)
4
+ end
@@ -0,0 +1,9 @@
1
+ class SunspotGenerator < Rails::Generator::Base
2
+
3
+ def manifest
4
+ record do |m|
5
+ m.template 'sunspot.yml', 'config/sunspot.yml'
6
+ end
7
+ end
8
+
9
+ end
@@ -0,0 +1,18 @@
1
+ production:
2
+ solr:
3
+ hostname: localhost
4
+ port: 8983
5
+ log_level: WARNING
6
+
7
+ development:
8
+ solr:
9
+ hostname: localhost
10
+ port: 8982
11
+ log_level: INFO
12
+
13
+ test:
14
+ solr:
15
+ hostname: localhost
16
+ port: 8981
17
+ log_level: WARNING
18
+
@@ -0,0 +1 @@
1
+ # Install hook code here
@@ -0,0 +1,58 @@
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 :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
+
13
+ class <<self
14
+ attr_writer :configuration
15
+
16
+ def configuration
17
+ @configuration ||= Sunspot::Rails::Configuration.new
18
+ end
19
+
20
+ def reset
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
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,160 @@
1
+ module Sunspot #:nodoc:
2
+ module Rails #:nodoc:
3
+ #
4
+ # This module provides Sunspot Adapter implementations for ActiveRecord
5
+ # models.
6
+ #
7
+ module Adapters
8
+ class ActiveRecordInstanceAdapter < Sunspot::Adapters::InstanceAdapter
9
+ #
10
+ # Return the primary key for the adapted instance
11
+ #
12
+ # ==== Returns
13
+ #
14
+ # Integer:: Database ID of model
15
+ #
16
+ def id
17
+ @instance.id
18
+ end
19
+ end
20
+
21
+ class ActiveResourceInstanceAdapter < Sunspot::Adapters::InstanceAdapter
22
+ #
23
+ # Return the primary key for the adapted instance
24
+ #
25
+ # ==== Returns
26
+ #
27
+ # Integer:: Database ID of model
28
+ #
29
+ def id
30
+ @instance.id
31
+ end
32
+ end
33
+
34
+ class ActiveRecordDataAccessor < Sunspot::Adapters::DataAccessor
35
+ # options for the find
36
+ attr_accessor :include, :select
37
+
38
+ #
39
+ # Set the fields to select from the database. This will be passed
40
+ # to ActiveRecord.
41
+ #
42
+ # ==== Parameters
43
+ #
44
+ # value<Mixed>:: String of comma-separated columns or array of columns
45
+ #
46
+ def select=(value)
47
+ value = value.join(', ') if value.respond_to?(:join)
48
+ @select = value
49
+ end
50
+
51
+ #
52
+ # Get one ActiveRecord instance out of the database by ID
53
+ #
54
+ # ==== Parameters
55
+ #
56
+ # id<String>:: Database ID of model to retreive
57
+ #
58
+ # ==== Returns
59
+ #
60
+ # ActiveRecord::Base:: ActiveRecord model
61
+ #
62
+ def load(id)
63
+ @clazz.first(options_for_find.merge(
64
+ :conditions => { @clazz.primary_key => id.to_i}
65
+ ))
66
+ end
67
+
68
+ #
69
+ # Get a collection of ActiveRecord instances out of the database by ID
70
+ #
71
+ # ==== Parameters
72
+ #
73
+ # ids<Array>:: Database IDs of models to retrieve
74
+ #
75
+ # ==== Returns
76
+ #
77
+ # Array:: Collection of ActiveRecord models
78
+ #
79
+ def load_all(ids)
80
+ @clazz.all(options_for_find.merge(
81
+ :conditions => { @clazz.primary_key => ids.map { |id| id.to_i }}
82
+ ))
83
+ end
84
+
85
+ private
86
+
87
+ def options_for_find
88
+ returning({}) do |options|
89
+ options[:include] = @include unless @include.blank?
90
+ options[:select] = @select unless @select.blank?
91
+ end
92
+ end
93
+ end
94
+
95
+
96
+ class ActiveResourceDataAccessor < Sunspot::Adapters::DataAccessor
97
+ # options for the find
98
+ attr_accessor :include, :select
99
+
100
+ #
101
+ # Set the fields to select from the database. This will be passed
102
+ # to ActiveRecord.
103
+ #
104
+ # ==== Parameters
105
+ #
106
+ # value<Mixed>:: String of comma-separated columns or array of columns
107
+ #
108
+ def select=(value)
109
+ value = value.join(', ') if value.respond_to?(:join)
110
+ @select = value
111
+ end
112
+
113
+ #
114
+ # Get one ActiveRecord instance out of the database by ID
115
+ #
116
+ # ==== Parameters
117
+ #
118
+ # id<String>:: Database ID of model to retreive
119
+ #
120
+ # ==== Returns
121
+ #
122
+ # ActiveRecord::Base:: ActiveRecord model
123
+ #
124
+ def load(id)
125
+ @clazz.first(options_for_find.merge(
126
+ :conditions => { @clazz.primary_key => id.to_i}
127
+ ))
128
+ end
129
+
130
+ #
131
+ # Get a collection of ActiveRecord instances out of the database by ID
132
+ #
133
+ # ==== Parameters
134
+ #
135
+ # ids<Array>:: Database IDs of models to retrieve
136
+ #
137
+ # ==== Returns
138
+ #
139
+ # Array:: Collection of ActiveRecord models
140
+ #
141
+ def load_all(ids)
142
+ @clazz.find(:all, options_for_find.merge(
143
+ :conditions => { @clazz.primary_key => ids.map { |id| id.to_i }}
144
+ ))
145
+ end
146
+
147
+ private
148
+
149
+ def options_for_find
150
+ returning({}) do |options|
151
+ options[:include] = @include unless @include.blank?
152
+ options[:select] = @select unless @select.blank?
153
+ end
154
+ end
155
+ end
156
+
157
+
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,272 @@
1
+ module Sunspot #:nodoc:
2
+ module Rails #:nodoc:
3
+ #
4
+ # Sunspot::Rails is configured via the config/sunspot.yml file, which
5
+ # contains properties keyed by environment name. A sample sunspot.yml file
6
+ # would look like:
7
+ #
8
+ # development:
9
+ # solr:
10
+ # hostname: localhost
11
+ # port: 8982
12
+ # min_memory: 512M
13
+ # max_memory: 1G
14
+ # solr_jar: /some/path/solr15/start.jar
15
+ # test:
16
+ # solr:
17
+ # hostname: localhost
18
+ # port: 8983
19
+ # log_level: OFF
20
+ # production:
21
+ # solr:
22
+ # hostname: localhost
23
+ # port: 8983
24
+ # path: /solr/myindex
25
+ # log_level: WARNING
26
+ # solr_home: /some/path
27
+ # master_solr:
28
+ # hostname: localhost
29
+ # port: 8982
30
+ # path: /solr
31
+ # auto_commit_after_request: true
32
+ #
33
+ # Sunspot::Rails uses the configuration to set up the Solr connection, as
34
+ # well as for starting Solr with the appropriate port using the
35
+ # <code>rake sunspot:solr:start</code> task.
36
+ #
37
+ # If the <code>master_solr</code> configuration is present, Sunspot will use
38
+ # the Solr instance specified here for all write operations, and the Solr
39
+ # configured under <code>solr</code> for all read operations.
40
+ #
41
+ class Configuration
42
+ attr_writer :user_configuration
43
+ #
44
+ # The host name at which to connect to Solr. Default 'localhost'.
45
+ #
46
+ # ==== Returns
47
+ #
48
+ # String:: host name
49
+ #
50
+ def hostname
51
+ @hostname ||= (user_configuration_from_key('solr', 'hostname') || 'localhost')
52
+ end
53
+
54
+ #
55
+ # The port at which to connect to Solr. Default 8983.
56
+ #
57
+ # ==== Returns
58
+ #
59
+ # Integer:: port
60
+ #
61
+ def port
62
+ @port ||= (user_configuration_from_key('solr', 'port') || 8983).to_i
63
+ end
64
+
65
+ #
66
+ # The url path to the Solr servlet (useful if you are running multicore).
67
+ # Default '/solr'.
68
+ #
69
+ # ==== Returns
70
+ #
71
+ # String:: path
72
+ #
73
+ def path
74
+ @path ||= (user_configuration_from_key('solr', 'path') || '/solr')
75
+ end
76
+
77
+ #
78
+ # The host name at which to connect to the master Solr instance. Defaults
79
+ # to the 'hostname' configuration option.
80
+ #
81
+ # ==== Returns
82
+ #
83
+ # String:: host name
84
+ #
85
+ def master_hostname
86
+ @master_hostname ||= (user_configuration_from_key('master_solr', 'hostname') || hostname)
87
+ end
88
+
89
+ #
90
+ # The port at which to connect to the master Solr instance. Defaults to
91
+ # the 'port' configuration option.
92
+ #
93
+ # ==== Returns
94
+ #
95
+ # Integer:: port
96
+ #
97
+ def master_port
98
+ @master_port ||= (user_configuration_from_key('master_solr', 'port') || port).to_i
99
+ end
100
+
101
+ #
102
+ # The path to the master Solr servlet (useful if you are running multicore).
103
+ # Defaults to the value of the 'path' configuration option.
104
+ #
105
+ # ==== Returns
106
+ #
107
+ # String:: path
108
+ #
109
+ def master_path
110
+ @master_path ||= (user_configuration_from_key('master_solr', 'path') || path)
111
+ end
112
+
113
+ #
114
+ # True if there is a master Solr instance configured, otherwise false.
115
+ #
116
+ # ==== Returns
117
+ #
118
+ # Boolean:: bool
119
+ #
120
+ def has_master?
121
+ @has_master = !!user_configuration_from_key('master_solr')
122
+ end
123
+
124
+ #
125
+ # The default log_level that should be passed to solr. You can
126
+ # change the individual log_levels in the solr admin interface.
127
+ # Default 'INFO'.
128
+ #
129
+ # ==== Returns
130
+ #
131
+ # String:: log_level
132
+ #
133
+ def log_level
134
+ @log_level ||= (user_configuration_from_key('solr', 'log_level') || 'INFO')
135
+ end
136
+
137
+ #
138
+ # Should the solr index receive a commit after each http-request.
139
+ # Default true
140
+ #
141
+ # ==== Returns
142
+ #
143
+ # Boolean: auto_commit_after_request?
144
+ #
145
+ def auto_commit_after_request?
146
+ @auto_commit_after_request ||=
147
+ user_configuration_from_key('auto_commit_after_request') != false
148
+ end
149
+
150
+ #
151
+ # As for #auto_commit_after_request? but only for deletes
152
+ # Default false
153
+ #
154
+ # ==== Returns
155
+ #
156
+ # Boolean: auto_commit_after_delete_request?
157
+ #
158
+ def auto_commit_after_delete_request?
159
+ @auto_commit_after_delete_request ||=
160
+ (user_configuration_from_key('auto_commit_after_delete_request') || false)
161
+ end
162
+
163
+
164
+ #
165
+ # The log directory for solr logfiles
166
+ #
167
+ # ==== Returns
168
+ #
169
+ # String:: log_dir
170
+ #
171
+ def log_file
172
+ @log_file ||= (user_configuration_from_key('solr', 'log_file') || default_log_file_location )
173
+ end
174
+
175
+ def data_path
176
+ @data_path ||= user_configuration_from_key('solr', 'data_path') || File.join(::Rails.root, 'solr', 'data', ::Rails.env)
177
+ end
178
+
179
+ def pid_path
180
+ @pids_path ||= user_configuration_from_key('solr', 'pid_path') || File.join(::Rails.root, 'solr', 'pids', ::Rails.env)
181
+ end
182
+
183
+ #
184
+ # The solr home directory. Sunspot::Rails expects this directory
185
+ # to contain a config, data and pids directory. See
186
+ # Sunspot::Rails::Server.bootstrap for more information.
187
+ #
188
+ # ==== Returns
189
+ #
190
+ # String:: solr_home
191
+ #
192
+ def solr_home
193
+ @solr_home ||=
194
+ if user_configuration_from_key('solr', 'solr_home')
195
+ user_configuration_from_key('solr', 'solr_home')
196
+ else
197
+ File.join(::Rails.root, 'solr')
198
+ end
199
+ end
200
+
201
+ #
202
+ # Solr start jar
203
+ #
204
+ def solr_jar
205
+ @solr_jar ||= user_configuration_from_key('solr', 'solr_jar')
206
+ end
207
+
208
+ #
209
+ # Minimum java heap size for Solr instance
210
+ #
211
+ def min_memory
212
+ @min_memory ||= user_configuration_from_key('solr', 'min_memory')
213
+ end
214
+
215
+ #
216
+ # Maximum java heap size for Solr instance
217
+ #
218
+ def max_memory
219
+ @max_memory ||= user_configuration_from_key('solr', 'max_memory')
220
+ end
221
+
222
+ private
223
+
224
+ #
225
+ # Logging in rails_root/log as solr_<environment>.log as a
226
+ # default.
227
+ #
228
+ # ===== Returns
229
+ #
230
+ # String:: default_log_file_location
231
+ #
232
+ def default_log_file_location
233
+ File.join(::Rails.root, 'log', "solr_" + ::Rails.env + ".log")
234
+ end
235
+
236
+ #
237
+ # return a specific key from the user configuration in config/sunspot.yml
238
+ #
239
+ # ==== Returns
240
+ #
241
+ # Mixed:: requested_key or nil
242
+ #
243
+ def user_configuration_from_key( *keys )
244
+ keys.inject(user_configuration) do |hash, key|
245
+ hash[key] if hash
246
+ end
247
+ end
248
+
249
+ #
250
+ # Memoized hash of configuration options for the current Rails environment
251
+ # as specified in config/sunspot.yml
252
+ #
253
+ # ==== Returns
254
+ #
255
+ # Hash:: configuration options for current environment
256
+ #
257
+ def user_configuration
258
+ @user_configuration ||=
259
+ begin
260
+ path = File.join(::Rails.root, 'config', 'sunspot.yml')
261
+ if File.exist?(path)
262
+ File.open(path) do |file|
263
+ YAML.load(file)[::Rails.env]
264
+ end
265
+ else
266
+ {}
267
+ end
268
+ end
269
+ end
270
+ end
271
+ end
272
+ end