robsharp-sunspot_rails 1.1.0.2

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