rails 0.13.1 → 0.14.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rails might be problematic. Click here for more details.

Files changed (86) hide show
  1. data/CHANGELOG +105 -0
  2. data/Rakefile +39 -17
  3. data/bin/breakpointer +2 -2
  4. data/bin/console +2 -22
  5. data/bin/destroy +2 -6
  6. data/bin/generate +2 -6
  7. data/bin/performance/benchmarker +3 -0
  8. data/bin/performance/profiler +3 -0
  9. data/bin/process/reaper +3 -0
  10. data/bin/process/spawner +3 -0
  11. data/bin/process/spinner +3 -0
  12. data/bin/rails +4 -0
  13. data/bin/runner +2 -27
  14. data/bin/server +2 -48
  15. data/configs/apache.conf +8 -0
  16. data/configs/database.yml +8 -8
  17. data/environments/boot.rb +17 -0
  18. data/environments/development.rb +10 -7
  19. data/environments/environment.rb +37 -73
  20. data/environments/production.rb +15 -6
  21. data/environments/test.rb +12 -6
  22. data/fresh_rakefile +6 -198
  23. data/helpers/application.rb +2 -2
  24. data/helpers/application_helper.rb +1 -1
  25. data/helpers/test_helper.rb +6 -19
  26. data/html/javascripts/controls.js +427 -165
  27. data/html/javascripts/dragdrop.js +256 -277
  28. data/html/javascripts/effects.js +766 -277
  29. data/html/javascripts/prototype.js +903 -217
  30. data/html/javascripts/scriptaculous.js +47 -0
  31. data/html/javascripts/slider.js +258 -0
  32. data/html/robots.txt +1 -0
  33. data/lib/binding_of_caller.rb +3 -1
  34. data/lib/breakpoint.rb +5 -5
  35. data/lib/breakpoint_client.rb +1 -1
  36. data/lib/code_statistics.rb +7 -4
  37. data/lib/commands.rb +17 -0
  38. data/lib/commands/breakpointer.rb +1 -0
  39. data/lib/commands/console.rb +22 -0
  40. data/lib/commands/destroy.rb +6 -0
  41. data/lib/commands/generate.rb +6 -0
  42. data/{bin → lib/commands/ncgi}/listener +0 -0
  43. data/{bin → lib/commands/ncgi}/tracker +0 -0
  44. data/lib/commands/performance/benchmarker.rb +26 -0
  45. data/{bin/profiler → lib/commands/performance/profiler.rb} +3 -2
  46. data/lib/commands/process/reaper.rb +130 -0
  47. data/lib/commands/process/spawner.rb +52 -0
  48. data/lib/commands/process/spinner.rb +57 -0
  49. data/lib/commands/runner.rb +27 -0
  50. data/lib/commands/server.rb +59 -0
  51. data/{bin/update → lib/commands/update.rb} +1 -2
  52. data/lib/dispatcher.rb +20 -3
  53. data/lib/fcgi_handler.rb +59 -41
  54. data/lib/initializer.rb +479 -0
  55. data/lib/rails_generator/base.rb +2 -2
  56. data/lib/rails_generator/commands.rb +59 -7
  57. data/lib/rails_generator/generators/applications/app/app_generator.rb +26 -15
  58. data/lib/rails_generator/generators/components/controller/controller_generator.rb +3 -2
  59. data/lib/rails_generator/generators/components/controller/templates/view.rhtml +1 -1
  60. data/lib/rails_generator/generators/components/mailer/USAGE +2 -3
  61. data/lib/rails_generator/generators/components/mailer/templates/unit_test.rb +1 -1
  62. data/lib/rails_generator/generators/components/migration/migration_generator.rb +3 -1
  63. data/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb +32 -31
  64. data/lib/rails_generator/generators/components/scaffold/templates/view_edit.rhtml +1 -1
  65. data/lib/rails_generator/generators/components/scaffold/templates/view_list.rhtml +1 -1
  66. data/lib/rails_generator/generators/components/scaffold/templates/view_new.rhtml +1 -1
  67. data/lib/rails_generator/lookup.rb +3 -3
  68. data/lib/rails_generator/options.rb +1 -0
  69. data/lib/rails_generator/scripts.rb +1 -1
  70. data/lib/rails_version.rb +9 -0
  71. data/lib/railties_path.rb +1 -0
  72. data/lib/rubyprof_ext.rb +1 -1
  73. data/lib/tasks/databases.rake +152 -0
  74. data/lib/tasks/documentation.rake +44 -0
  75. data/lib/tasks/framework.rake +33 -0
  76. data/lib/tasks/javascripts.rake +6 -0
  77. data/lib/tasks/misc.rake +15 -0
  78. data/lib/tasks/rails.rb +7 -0
  79. data/lib/tasks/statistics.rake +16 -0
  80. data/lib/tasks/testing.rake +37 -0
  81. data/lib/test_help.rb +13 -0
  82. data/lib/webrick_server.rb +31 -9
  83. metadata +121 -85
  84. data/bin/benchmarker +0 -19
  85. data/bin/breakpointer_for_gem +0 -4
  86. data/bin/console_sandbox +0 -0
@@ -1,16 +1,17 @@
1
1
  require 'fcgi'
2
2
  require 'logger'
3
3
  require 'dispatcher'
4
+ require 'rbconfig'
4
5
 
5
6
  class RailsFCGIHandler
6
7
  SIGNALS = {
7
8
  'HUP' => :reload,
8
- 'TERM' => :graceful_exit,
9
- 'USR1' => :graceful_exit
9
+ 'TERM' => :exit,
10
+ 'USR1' => :exit,
11
+ 'USR2' => :restart
10
12
  }
11
13
 
12
14
  attr_reader :when_ready
13
- attr_reader :processing
14
15
 
15
16
  attr_accessor :log_file_path
16
17
  attr_accessor :gc_request_period
@@ -27,9 +28,6 @@ class RailsFCGIHandler
27
28
  # (default nil for normal GC behavior.) Optionally, pass a block which
28
29
  # takes this instance as an argument for further configuration.
29
30
  def initialize(log_file_path = nil, gc_request_period = nil)
30
- @when_ready = nil
31
- @processing = false
32
-
33
31
  self.log_file_path = log_file_path || "#{RAILS_ROOT}/log/fastcgi.crash.log"
34
32
  self.gc_request_period = gc_request_period
35
33
 
@@ -42,42 +40,37 @@ class RailsFCGIHandler
42
40
  # Start error timestamp at 11 seconds ago.
43
41
  @last_error_on = Time.now - 11
44
42
 
45
- dispatcher_log(:info, "starting")
43
+ dispatcher_log :info, "starting"
46
44
  end
47
45
 
48
46
  def process!(provider = FCGI)
49
47
  # Make a note of $" so we can safely reload this instance.
50
48
  mark!
51
49
 
52
- # Begin countdown to garbage collection.
53
50
  run_gc! if gc_request_period
54
51
 
55
52
  provider.each_cgi do |cgi|
56
- # Safely reload this instance if requested.
57
- if when_ready == :reload
58
- run_gc! if gc_request_period
59
- restore!
60
- @when_ready = nil
61
- dispatcher_log(:info, "reloaded")
62
- end
63
-
64
53
  process_request(cgi)
65
54
 
66
- # Break if graceful exit requested.
67
- break if when_ready == :exit
68
-
69
- # Garbage collection countdown.
70
- if gc_request_period
71
- @gc_request_countdown -= 1
72
- run_gc! if @gc_request_countdown <= 0
55
+ case when_ready
56
+ when :reload
57
+ reload!
58
+ when :restart
59
+ close_connection(cgi)
60
+ restart!
61
+ when :exit
62
+ close_connection(cgi)
63
+ break
73
64
  end
65
+
66
+ gc_countdown
74
67
  end
75
68
 
76
69
  GC.enable
77
- dispatcher_log(:info, "terminated gracefully")
70
+ dispatcher_log :info, "terminated gracefully"
78
71
 
79
72
  rescue SystemExit => exit_error
80
- dispatcher_log(:info, "terminated by explicit exit")
73
+ dispatcher_log :info, "terminated by explicit exit"
81
74
 
82
75
  rescue Object => fcgi_error
83
76
  # retry on errors that would otherwise have terminated the FCGI process,
@@ -105,7 +98,7 @@ class RailsFCGIHandler
105
98
  STDERR << " #{log_error.class}: #{log_error.message}\n"
106
99
  end
107
100
 
108
- def dispatcher_error(e,msg="")
101
+ def dispatcher_error(e, msg = "")
109
102
  error_message =
110
103
  "Dispatcher failed to catch: #{e} (#{e.class})\n" +
111
104
  " #{e.backtrace.join("\n ")}\n#{msg}"
@@ -114,39 +107,53 @@ class RailsFCGIHandler
114
107
 
115
108
  def install_signal_handlers
116
109
  SIGNALS.each do |signal, handler_name|
117
- install_signal_handler signal, method("#{handler_name}_handler").to_proc
110
+ install_signal_handler(signal, method("#{handler_name}_handler").to_proc)
118
111
  end
119
112
  end
120
113
 
121
114
  def install_signal_handler(signal, handler)
122
- trap signal, handler
115
+ trap(signal, handler)
123
116
  rescue ArgumentError
124
117
  dispatcher_log :warn, "Ignoring unsupported signal #{signal}."
125
118
  end
126
119
 
127
- def graceful_exit_handler(signal)
128
- if processing
129
- dispatcher_log :info, "asked to terminate ASAP"
130
- @when_ready = :exit
131
- else
132
- dispatcher_log :info, "told to terminate NOW"
133
- exit
134
- end
120
+ def exit_handler(signal)
121
+ dispatcher_log :info, "asked to terminate ASAP"
122
+ @when_ready = :exit
135
123
  end
136
124
 
137
125
  def reload_handler(signal)
138
- @when_ready = :reload
139
126
  dispatcher_log :info, "asked to reload ASAP"
127
+ @when_ready = :reload
128
+ end
129
+
130
+ def restart_handler(signal)
131
+ dispatcher_log :info, "asked to restart ASAP"
132
+ @when_ready = :restart
140
133
  end
141
134
 
142
135
  def process_request(cgi)
143
- @processing = true
144
136
  Dispatcher.dispatch(cgi)
145
137
  rescue Object => e
146
138
  raise if SignalException === e
147
139
  dispatcher_error(e)
148
- ensure
149
- @processing = false
140
+ end
141
+
142
+ def restart!
143
+ config = ::Config::CONFIG
144
+ ruby = File::join(config['bindir'], config['ruby_install_name']) + config['EXEEXT']
145
+ command_line = [ruby, $0, ARGV].flatten.join(' ')
146
+
147
+ dispatcher_log :info, "restarted"
148
+
149
+ exec(command_line)
150
+ end
151
+
152
+ def reload!
153
+ run_gc! if gc_request_period
154
+ restore!
155
+ @when_ready = nil
156
+ dispatcher_log :info, "reloaded"
150
157
  end
151
158
 
152
159
  def mark!
@@ -163,4 +170,15 @@ class RailsFCGIHandler
163
170
  @gc_request_countdown = gc_request_period
164
171
  GC.enable; GC.start; GC.disable
165
172
  end
166
- end
173
+
174
+ def gc_countdown
175
+ if gc_request_period
176
+ @gc_request_countdown -= 1
177
+ run_gc! if @gc_request_countdown <= 0
178
+ end
179
+ end
180
+
181
+ def close_connection(cgi)
182
+ cgi.instance_variable_get("@request").finish
183
+ end
184
+ end
@@ -0,0 +1,479 @@
1
+ require 'logger'
2
+
3
+ RAILS_ENV = (ENV['RAILS_ENV'] || 'development').dup unless defined?(RAILS_ENV)
4
+
5
+ module Rails
6
+ # The Initializer is responsible for processing the Rails configuration, such
7
+ # as setting the $LOAD_PATH, requiring the right frameworks, initializing
8
+ # logging, and more. It can be run either as a single command that'll just
9
+ # use the default configuration, like this:
10
+ #
11
+ # Rails::Initializer.run
12
+ #
13
+ # But normally it's more interesting to pass in a custom configuration
14
+ # through the block running:
15
+ #
16
+ # Rails::Initializer.run do |config|
17
+ # config.frameworks -= [ :action_web_service ]
18
+ # end
19
+ #
20
+ # This will use the default configuration options from Rails::Configuration,
21
+ # but allow for overwriting on select areas.
22
+ class Initializer
23
+ # The Configuration instance used by this Initializer instance.
24
+ attr_reader :configuration
25
+
26
+ # Runs the initializer. By default, this will invoke the #process method,
27
+ # which simply executes all of the initialization routines. Alternately,
28
+ # you can specify explicitly which initialization routine you want:
29
+ #
30
+ # Rails::Initializer.run(:set_load_path)
31
+ #
32
+ # This is useful if you only want the load path initialized, without
33
+ # incuring the overhead of completely loading the entire environment.
34
+ def self.run(command = :process, configuration = Configuration.new)
35
+ yield configuration if block_given?
36
+ new(configuration).send(command)
37
+ end
38
+
39
+ # Create a new Initializer instance that references the given Configuration
40
+ # instance.
41
+ def initialize(configuration)
42
+ @configuration = configuration
43
+ end
44
+
45
+ # Sequentially step through all of the available initialization routines,
46
+ # in order:
47
+ #
48
+ # * #set_load_path
49
+ # * #set_connection_adapters
50
+ # * #require_frameworks
51
+ # * #load_environment
52
+ # * #initialize_database
53
+ # * #initialize_logger
54
+ # * #initialize_framework_logging
55
+ # * #initialize_framework_views
56
+ # * #initialize_routing
57
+ # * #initialize_dependency_mechanism
58
+ # * #initialize_breakpoints
59
+ # * #initialize_whiny_nils
60
+ # * #intitialize_framework_settings
61
+ # * #load_environment
62
+ # * #load_plugins
63
+ #
64
+ # (Note that #load_environment is invoked twice, once at the start and
65
+ # once at the end, to support the legacy configuration style where the
66
+ # environment could overwrite the defaults directly, instead of via the
67
+ # Configuration instance.
68
+ def process
69
+ set_load_path
70
+ set_connection_adapters
71
+
72
+ require_frameworks
73
+ load_environment
74
+
75
+ initialize_database
76
+ initialize_logger
77
+ initialize_framework_logging
78
+ initialize_framework_views
79
+ initialize_routing
80
+ initialize_dependency_mechanism
81
+ initialize_breakpoints
82
+ initialize_whiny_nils
83
+
84
+ intitialize_framework_settings
85
+
86
+ # Support for legacy configuration style where the environment
87
+ # could overwrite anything set from the defaults/global through
88
+ # the individual base class configurations.
89
+ load_environment
90
+
91
+ load_plugins
92
+ end
93
+
94
+ # Set the <tt>$LOAD_PATH</tt> based on the value of
95
+ # Configuration#load_paths. Duplicates are removed.
96
+ def set_load_path
97
+ configuration.load_paths.reverse.each { |dir| $LOAD_PATH.unshift(dir) if File.directory?(dir) }
98
+ $LOAD_PATH.uniq!
99
+ end
100
+
101
+ # Sets the +RAILS_CONNECTION_ADAPTERS+ constant based on the value of
102
+ # Configuration#connection_adapters. This constant is used to determine
103
+ # which database adapters should be loaded (by default, all adapters are
104
+ # loaded).
105
+ def set_connection_adapters
106
+ Object.const_set("RAILS_CONNECTION_ADAPTERS", configuration.connection_adapters) if configuration.connection_adapters
107
+ end
108
+
109
+ # Requires all frameworks specified by the Configuration#frameworks
110
+ # list. By default, all frameworks (ActiveRecord, ActiveSupport,
111
+ # ActionPack, ActionMailer, and ActionWebService) are loaded.
112
+ def require_frameworks
113
+ configuration.frameworks.each { |framework| require(framework.to_s) }
114
+ end
115
+
116
+ # Loads all plugins in the <tt>vendor/plugins</tt> directory. Each
117
+ # subdirectory of <tt>vendor/plugins</tt> is inspected as follows:
118
+ #
119
+ # * if the directory has a +lib+ subdirectory, add it to the load path
120
+ # * if the directory contains an <tt>init.rb</tt> file, read it in and
121
+ # eval it.
122
+ #
123
+ # After all plugins are loaded, duplicates are removed from the load path.
124
+ def load_plugins
125
+ config = configuration
126
+
127
+ Dir.glob("#{configuration.plugins_path}/*") do |directory|
128
+ next if File.basename(directory)[0] == ?. || !File.directory?(directory)
129
+
130
+ if File.directory?("#{directory}/lib")
131
+ $LOAD_PATH.unshift "#{directory}/lib"
132
+ end
133
+
134
+ if File.exist?("#{directory}/init.rb")
135
+ silence_warnings do
136
+ eval(IO.read("#{directory}/init.rb"), binding)
137
+ end
138
+ end
139
+ end
140
+
141
+ $LOAD_PATH.uniq!
142
+ end
143
+
144
+ # Loads the environment specified by Configuration#environment_path, which
145
+ # is typically one of development, testing, or production.
146
+ def load_environment
147
+ silence_warnings do
148
+ config = configuration
149
+ eval(IO.read(configuration.environment_path), binding)
150
+ end
151
+ end
152
+
153
+ # This initialization routine does nothing unless <tt>:active_record</tt>
154
+ # is one of the frameworks to load (Configuration#frameworks). If it is,
155
+ # this sets the database configuration from Configuration#database_configuration
156
+ # and then establishes the connection.
157
+ def initialize_database
158
+ return unless configuration.frameworks.include?(:active_record)
159
+ ActiveRecord::Base.configurations = configuration.database_configuration
160
+ ActiveRecord::Base.establish_connection
161
+ end
162
+
163
+ # If the +RAILS_DEFAULT_LOGGER+ constant is already set, this initialization
164
+ # routine does nothing. If the constant is not set, and Configuration#logger
165
+ # is not +nil+, this also does nothing. Otherwise, a new logger instance
166
+ # is created at Configuration#log_path, with a default log level of
167
+ # Configuration#log_level.
168
+ #
169
+ # If the log could not be created, the log will be set to output to
170
+ # +STDERR+, with a log level of +WARN+.
171
+ def initialize_logger
172
+ # if the environment has explicitly defined a logger, use it
173
+ return if defined?(RAILS_DEFAULT_LOGGER)
174
+
175
+ unless logger = configuration.logger
176
+ begin
177
+ logger = Logger.new(configuration.log_path)
178
+ logger.level = Logger.const_get(configuration.log_level.to_s.upcase)
179
+ rescue StandardError
180
+ logger = Logger.new(STDERR)
181
+ logger.level = Logger::WARN
182
+ logger.warn(
183
+ "Rails Error: Unable to access log file. Please ensure that #{configuration.log_path} exists and is chmod 0666. " +
184
+ "The log level has been raised to WARN and the output directed to STDERR until the problem is fixed."
185
+ )
186
+ end
187
+ end
188
+
189
+ silence_warnings { Object.const_set "RAILS_DEFAULT_LOGGER", logger }
190
+ end
191
+
192
+ # Sets the logger for ActiveRecord, ActionController, and ActionMailer
193
+ # (but only for those frameworks that are to be loaded). If the framework's
194
+ # logger is already set, it is not changed, otherwise it is set to use
195
+ # +RAILS_DEFAULT_LOGGER+.
196
+ def initialize_framework_logging
197
+ for framework in ([ :active_record, :action_controller, :action_mailer ] & configuration.frameworks)
198
+ framework.to_s.camelize.constantize.const_get("Base").logger ||= RAILS_DEFAULT_LOGGER
199
+ end
200
+ end
201
+
202
+ # Sets the +template_root+ for ActionController::Base and ActionMailer::Base
203
+ # (but only for those frameworks that are to be loaded). If the framework's
204
+ # +template_root+ has already been set, it is not changed, otherwise it is
205
+ # set to use Configuration#view_path.
206
+ def initialize_framework_views
207
+ for framework in ([ :action_controller, :action_mailer ] & configuration.frameworks)
208
+ framework.to_s.camelize.constantize.const_get("Base").template_root ||= configuration.view_path
209
+ end
210
+ end
211
+
212
+ # If ActionController is not one of the loaded frameworks (Configuration#frameworks)
213
+ # this does nothing. Otherwise, it loads the routing definitions and sets up
214
+ # loading module used to lazily load controllers (Configuration#controller_paths).
215
+ def initialize_routing
216
+ return unless configuration.frameworks.include?(:action_controller)
217
+ ActionController::Routing::Routes.reload
218
+ Object.const_set "Controllers", Dependencies::LoadingModule.root(*configuration.controller_paths)
219
+ end
220
+
221
+ # Sets the dependency loading mechanism based on the value of
222
+ # Configuration#cache_classes.
223
+ def initialize_dependency_mechanism
224
+ Dependencies.mechanism = configuration.cache_classes ? :require : :load
225
+ end
226
+
227
+ # Sets the +BREAKPOINT_SERVER_PORT+ if Configuration#breakpoint_server
228
+ # is true.
229
+ def initialize_breakpoints
230
+ silence_warnings { Object.const_set("BREAKPOINT_SERVER_PORT", 42531) if configuration.breakpoint_server }
231
+ end
232
+
233
+ # Loads support for "whiny nil" (noisy warnings when methods are invoked
234
+ # on +nil+ values) if Configuration#whiny_nils is true.
235
+ def initialize_whiny_nils
236
+ require('active_support/whiny_nil') if configuration.whiny_nils
237
+ end
238
+
239
+ # Initialize framework-specific settings for each of the loaded frameworks
240
+ # (Configuration#frameworks). The available settings map to the accessors
241
+ # on each of the corresponding Base classes.
242
+ def intitialize_framework_settings
243
+ configuration.frameworks.each do |framework|
244
+ base_class = framework.to_s.camelize.constantize.const_get("Base")
245
+
246
+ configuration.send(framework).each do |setting, value|
247
+ base_class.send("#{setting}=", value)
248
+ end
249
+ end
250
+ end
251
+ end
252
+
253
+ # The Configuration class holds all the parameters for the Initializer and
254
+ # ships with defaults that suites most Rails applications. But it's possible
255
+ # to overwrite everything. Usually, you'll create an Configuration file
256
+ # implicitly through the block running on the Initializer, but it's also
257
+ # possible to create the Configuration instance in advance and pass it in
258
+ # like this:
259
+ #
260
+ # config = Rails::Configuration.new
261
+ # Rails::Initializer.run(:process, config)
262
+ class Configuration
263
+ # A stub for setting options on ActionController::Base
264
+ attr_accessor :action_controller
265
+
266
+ # A stub for setting options on ActionMailer::Base
267
+ attr_accessor :action_mailer
268
+
269
+ # A stub for setting options on ActionView::Base
270
+ attr_accessor :action_view
271
+
272
+ # A stub for setting options on ActionWebService::Base
273
+ attr_accessor :action_web_service
274
+
275
+ # A stub for setting options on ActiveRecord::Base
276
+ attr_accessor :active_record
277
+
278
+ # Whether or not to use the breakpoint server (boolean)
279
+ attr_accessor :breakpoint_server
280
+
281
+ # Whether or not classes should be cached (set to false if you want
282
+ # application classes to be reloaded on each request)
283
+ attr_accessor :cache_classes
284
+
285
+ # The list of connection adapters to load. (By default, all connection
286
+ # adapters are loaded. You can set this to be just the adapter(s) you
287
+ # will use to reduce your application's load time.)
288
+ attr_accessor :connection_adapters
289
+
290
+ # The list of paths that should be searched for controllers. (Defaults
291
+ # to <tt>app/controllers</tt> and <tt>components</tt>.)
292
+ attr_accessor :controller_paths
293
+
294
+ # The path to the database configuration file to use. (Defaults to
295
+ # <tt>config/database.yml</tt>.)
296
+ attr_accessor :database_configuration_file
297
+
298
+ # The list of rails framework components that should be loaded. (Defaults
299
+ # to <tt>:active_record</tt>, <tt>:action_controller</tt>,
300
+ # <tt>:action_view</tt>, <tt>:action_mailer</tt>, and
301
+ # <tt>:action_web_service</tt>).
302
+ attr_accessor :frameworks
303
+
304
+ # An array of additional paths to prepend to the load path. By default,
305
+ # all +app+, +lib+, +vendor+ and mock paths are included in this list.
306
+ attr_accessor :load_paths
307
+
308
+ # The log level to use for the default Rails logger. In production mode,
309
+ # this defaults to <tt>:info</tt>. In development mode, it defaults to
310
+ # <tt>:debug</tt>.
311
+ attr_accessor :log_level
312
+
313
+ # The path to the log file to use. Defaults to log/#{environment}.log
314
+ # (e.g. log/development.log or log/production.log).
315
+ attr_accessor :log_path
316
+
317
+ # The specific logger to use. By default, a logger will be created and
318
+ # initialized using #log_path and #log_level, but a programmer may
319
+ # specifically set the logger to use via this accessor and it will be
320
+ # used directly.
321
+ attr_accessor :logger
322
+
323
+ # The root of the application's views. (Defaults to <tt>app/views</tt>.)
324
+ attr_accessor :view_path
325
+
326
+ # Set to +true+ if you want to be warned (noisily) when you try to invoke
327
+ # any method of +nil+. Set to +false+ for the standard Ruby behavior.
328
+ attr_accessor :whiny_nils
329
+
330
+ # Create a new Configuration instance, initialized with the default
331
+ # values.
332
+ def initialize
333
+ self.frameworks = default_frameworks
334
+ self.load_paths = default_load_paths
335
+ self.log_path = default_log_path
336
+ self.log_level = default_log_level
337
+ self.view_path = default_view_path
338
+ self.controller_paths = default_controller_paths
339
+ self.cache_classes = default_cache_classes
340
+ self.breakpoint_server = default_breakpoint_server
341
+ self.whiny_nils = default_whiny_nils
342
+ self.database_configuration_file = default_database_configuration_file
343
+
344
+ for framework in default_frameworks
345
+ self.send("#{framework}=", OrderedOptions.new)
346
+ end
347
+ end
348
+
349
+ # Loads and returns the contents of the #database_configuration_file. The
350
+ # contents of the file are processed via ERB before being sent through
351
+ # YAML::load.
352
+ def database_configuration
353
+ YAML::load(ERB.new(IO.read(database_configuration_file)).result)
354
+ end
355
+
356
+ # The path to the current environment's file (development.rb, etc.). By
357
+ # default the file is at <tt>config/environments/#{environment}.rb</tt>.
358
+ def environment_path
359
+ "#{RAILS_ROOT}/config/environments/#{environment}.rb"
360
+ end
361
+
362
+ # The path to the root of the plugins directory. By default, it is in
363
+ # <tt>vendor/plugins</tt>.
364
+ def plugins_path
365
+ "#{RAILS_ROOT}/vendor/plugins"
366
+ end
367
+
368
+ # Return the currently selected environment. By default, it returns the
369
+ # value of the +RAILS_ENV+ constant.
370
+ def environment
371
+ ::RAILS_ENV
372
+ end
373
+
374
+ private
375
+ def default_frameworks
376
+ [ :active_record, :action_controller, :action_view, :action_mailer, :action_web_service ]
377
+ end
378
+
379
+ def default_load_paths
380
+ paths = ["#{RAILS_ROOT}/test/mocks/#{environment}"]
381
+
382
+ # Then model subdirectories.
383
+ # TODO: Don't include .rb models as load paths
384
+ paths.concat(Dir["#{RAILS_ROOT}/app/models/[_a-z]*"])
385
+ paths.concat(Dir["#{RAILS_ROOT}/components/[_a-z]*"])
386
+
387
+ # Followed by the standard includes.
388
+ # TODO: Don't include dirs for frameworks that are not used
389
+ paths.concat %w(
390
+ app
391
+ app/models
392
+ app/controllers
393
+ app/helpers
394
+ app/apis
395
+ components
396
+ config
397
+ lib
398
+ vendor
399
+ vendor/rails/railties
400
+ vendor/rails/railties/lib
401
+ vendor/rails/actionpack/lib
402
+ vendor/rails/activesupport/lib
403
+ vendor/rails/activerecord/lib
404
+ vendor/rails/actionmailer/lib
405
+ vendor/rails/actionwebservice/lib
406
+ ).map { |dir| "#{RAILS_ROOT}/#{dir}" }.select { |dir| File.directory?(dir) }
407
+ end
408
+
409
+ def default_log_path
410
+ File.join(RAILS_ROOT, 'log', "#{environment}.log")
411
+ end
412
+
413
+ def default_log_level
414
+ environment == 'production' ? :info : :debug
415
+ end
416
+
417
+ def default_database_configuration_file
418
+ File.join(RAILS_ROOT, 'config', 'database.yml')
419
+ end
420
+
421
+ def default_view_path
422
+ File.join(RAILS_ROOT, 'app', 'views')
423
+ end
424
+
425
+ def default_controller_paths
426
+ [ File.join(RAILS_ROOT, 'app', 'controllers'), File.join(RAILS_ROOT, 'components') ]
427
+ end
428
+
429
+ def default_dependency_mechanism
430
+ :load
431
+ end
432
+
433
+ def default_cache_classes
434
+ false
435
+ end
436
+
437
+ def default_breakpoint_server
438
+ false
439
+ end
440
+
441
+ def default_whiny_nils
442
+ false
443
+ end
444
+ end
445
+ end
446
+
447
+ # Needs to be duplicated from Active Support since its needed before Active
448
+ # Support is available.
449
+ class OrderedOptions < Array # :nodoc:
450
+ def []=(key, value)
451
+ key = key.to_sym
452
+
453
+ if pair = find_pair(key)
454
+ pair.pop
455
+ pair << value
456
+ else
457
+ self << [key, value]
458
+ end
459
+ end
460
+
461
+ def [](key)
462
+ pair = find_pair(key.to_sym)
463
+ pair ? pair.last : nil
464
+ end
465
+
466
+ def method_missing(name, *args)
467
+ if name.to_s =~ /(.*)=$/
468
+ self[$1.to_sym] = args.first
469
+ else
470
+ self[name]
471
+ end
472
+ end
473
+
474
+ private
475
+ def find_pair(key)
476
+ self.each { |i| return i if i.first == key }
477
+ return false
478
+ end
479
+ end