rails 1.0.0 → 1.1.0

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 (76) hide show
  1. data/CHANGELOG +152 -10
  2. data/README +30 -5
  3. data/Rakefile +18 -13
  4. data/bin/rails +1 -11
  5. data/{lib/rails_info.rb → builtin/rails_info/rails/info.rb} +25 -8
  6. data/builtin/{controllers/rails_info_controller.rb → rails_info/rails/info_controller.rb} +2 -2
  7. data/configs/databases/mysql.yml +47 -0
  8. data/configs/databases/oracle.yml +30 -0
  9. data/configs/databases/postgresql.yml +44 -0
  10. data/configs/databases/sqlite2.yml +16 -0
  11. data/configs/databases/sqlite3.yml +16 -0
  12. data/configs/lighttpd.conf +11 -5
  13. data/configs/routes.rb +5 -2
  14. data/environments/development.rb +3 -2
  15. data/environments/environment.rb +5 -8
  16. data/environments/production.rb +1 -2
  17. data/environments/test.rb +1 -1
  18. data/fresh_rakefile +2 -2
  19. data/html/500.html +1 -1
  20. data/html/index.html +3 -3
  21. data/html/javascripts/application.js +2 -0
  22. data/html/javascripts/controls.js +95 -30
  23. data/html/javascripts/dragdrop.js +161 -21
  24. data/html/javascripts/effects.js +310 -211
  25. data/html/javascripts/prototype.js +228 -28
  26. data/lib/code_statistics.rb +1 -1
  27. data/lib/commands/console.rb +3 -1
  28. data/lib/commands/plugin.rb +113 -70
  29. data/lib/commands/process/reaper.rb +1 -1
  30. data/lib/commands/process/spawner.rb +33 -4
  31. data/lib/commands/runner.rb +1 -1
  32. data/lib/commands/server.rb +3 -1
  33. data/lib/commands/servers/lighttpd.rb +41 -9
  34. data/lib/console_app.rb +27 -0
  35. data/lib/console_with_helpers.rb +23 -0
  36. data/lib/dispatcher.rb +8 -8
  37. data/lib/fcgi_handler.rb +22 -4
  38. data/lib/initializer.rb +107 -38
  39. data/lib/rails_generator/commands.rb +17 -7
  40. data/lib/rails_generator/generators/applications/app/app_generator.rb +30 -18
  41. data/lib/rails_generator/generators/components/integration_test/USAGE +14 -0
  42. data/lib/rails_generator/generators/components/integration_test/integration_test_generator.rb +16 -0
  43. data/lib/rails_generator/generators/components/integration_test/templates/integration_test.rb +10 -0
  44. data/lib/rails_generator/generators/components/mailer/USAGE +1 -1
  45. data/lib/rails_generator/generators/components/migration/USAGE +1 -1
  46. data/lib/rails_generator/generators/components/model/USAGE +3 -1
  47. data/lib/rails_generator/generators/components/model/model_generator.rb +16 -0
  48. data/lib/rails_generator/generators/components/model/templates/migration.rb +11 -0
  49. data/lib/rails_generator/generators/components/model/templates/unit_test.rb +1 -1
  50. data/lib/rails_generator/generators/components/plugin/USAGE +3 -1
  51. data/lib/rails_generator/generators/components/plugin/plugin_generator.rb +1 -0
  52. data/lib/rails_generator/generators/components/plugin/templates/Rakefile +1 -1
  53. data/lib/rails_generator/generators/components/plugin/templates/install.rb +1 -0
  54. data/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb +1 -1
  55. data/lib/rails_generator/generators/components/scaffold/templates/controller.rb +4 -0
  56. data/lib/rails_generator/generators/components/scaffold/templates/style.css +4 -4
  57. data/lib/rails_generator/generators/components/scaffold/templates/view_list.rhtml +1 -1
  58. data/lib/rails_generator/generators/components/session_migration/USAGE +1 -1
  59. data/lib/rails_generator/options.rb +2 -2
  60. data/lib/rails_version.rb +1 -1
  61. data/lib/ruby_version_check.rb +17 -0
  62. data/lib/tasks/databases.rake +141 -139
  63. data/lib/tasks/documentation.rake +73 -68
  64. data/lib/tasks/framework.rake +86 -58
  65. data/lib/tasks/log.rake +9 -0
  66. data/lib/tasks/misc.rake +2 -17
  67. data/lib/tasks/pre_namespace_aliases.rake +46 -0
  68. data/lib/tasks/statistics.rake +9 -8
  69. data/lib/tasks/testing.rake +81 -29
  70. data/lib/tasks/tmp.rake +30 -0
  71. data/lib/test_help.rb +1 -0
  72. data/lib/webrick_server.rb +6 -8
  73. metadata +284 -271
  74. data/bin/process/spinner +0 -3
  75. data/configs/database.yml +0 -85
  76. data/lib/tasks/javascripts.rake +0 -6
@@ -127,4 +127,4 @@ ARGV.options do |opts|
127
127
  opts.parse!
128
128
  end
129
129
 
130
- ProgramProcess.process_keywords(OPTIONS[:action], OPTIONS[:dispatcher])
130
+ ProgramProcess.process_keywords(OPTIONS[:action], OPTIONS[:dispatcher])
@@ -1,8 +1,22 @@
1
1
  require 'optparse'
2
+ require 'socket'
2
3
 
3
4
  def spawn(port)
4
- print "Starting FCGI on port: #{port}\n "
5
- system("#{OPTIONS[:spawner]} -f #{OPTIONS[:dispatcher]} -p #{port}")
5
+ print "Checking if something is already running on port #{port}..."
6
+ begin
7
+ srv = TCPServer.new('0.0.0.0', port)
8
+ srv.close
9
+ srv = nil
10
+ print "NO\n "
11
+ print "Starting FCGI on port: #{port}\n "
12
+ system("#{OPTIONS[:spawner]} -f #{OPTIONS[:dispatcher]} -p #{port}")
13
+ rescue
14
+ print "YES\n"
15
+ end
16
+ end
17
+
18
+ def spawn_all
19
+ OPTIONS[:instances].times { |i| spawn(OPTIONS[:port] + i) }
6
20
  end
7
21
 
8
22
  OPTIONS = {
@@ -10,7 +24,8 @@ OPTIONS = {
10
24
  :spawner => '/usr/bin/env spawn-fcgi',
11
25
  :dispatcher => File.expand_path(RAILS_ROOT + '/public/dispatch.fcgi'),
12
26
  :port => 8000,
13
- :instances => 3
27
+ :instances => 3,
28
+ :repeat => nil
14
29
  }
15
30
 
16
31
  ARGV.options do |opts|
@@ -28,15 +43,20 @@ ARGV.options do |opts|
28
43
  You decide a starting port (default is 8000) and the number of FCGI process instances you'd
29
44
  like to run. So if you pick 9100 and 3 instances, you'll start processes on 9100, 9101, and 9102.
30
45
 
46
+ By setting the repeat option, you get a protection loop, which will attempt to restart any FCGI processes
47
+ that might have been exited or outright crashed.
48
+
31
49
  Examples:
32
50
  spawner # starts instances on 8000, 8001, and 8002
33
51
  spawner -p 9100 -i 10 # starts 10 instances counting from 9100 to 9109
52
+ spawner -p 9100 -r 5 # starts 3 instances counting from 9100 to 9102 and attempts start them every 5 seconds
34
53
  EOF
35
54
 
36
55
  opts.on(" Options:")
37
56
 
38
57
  opts.on("-p", "--port=number", Integer, "Starting port number (default: #{OPTIONS[:port]})") { |OPTIONS[:port]| }
39
58
  opts.on("-i", "--instances=number", Integer, "Number of instances (default: #{OPTIONS[:instances]})") { |OPTIONS[:instances]| }
59
+ opts.on("-r", "--repeat=seconds", Integer, "Repeat spawn attempts every n seconds (default: off)") { |OPTIONS[:repeat]| }
40
60
  opts.on("-e", "--environment=name", String, "test|development|production (default: #{OPTIONS[:environment]})") { |OPTIONS[:environment]| }
41
61
  opts.on("-s", "--spawner=path", String, "default: #{OPTIONS[:spawner]}") { |OPTIONS[:spawner]| }
42
62
  opts.on("-d", "--dispatcher=path", String, "default: #{OPTIONS[:dispatcher]}") { |dispatcher| OPTIONS[:dispatcher] = File.expand_path(dispatcher) }
@@ -49,4 +69,13 @@ ARGV.options do |opts|
49
69
  end
50
70
 
51
71
  ENV["RAILS_ENV"] = OPTIONS[:environment]
52
- OPTIONS[:instances].times { |i| spawn(OPTIONS[:port] + i) }
72
+
73
+ if OPTIONS[:repeat]
74
+ loop do
75
+ spawn_all
76
+ puts "Sleeping for #{OPTIONS[:repeat]} seconds"
77
+ sleep OPTIONS[:repeat]
78
+ end
79
+ else
80
+ spawn_all
81
+ end
@@ -24,4 +24,4 @@ ENV["RAILS_ENV"] = options[:environment]
24
24
  RAILS_ENV.replace(options[:environment]) if defined?(RAILS_ENV)
25
25
 
26
26
  require RAILS_ROOT + '/config/environment'
27
- eval(ARGV.first)
27
+ ARGV.empty? ? puts("Usage: runner 'code' [options]") : eval(ARGV.first)
@@ -1,4 +1,5 @@
1
1
  require 'active_support'
2
+ require 'fileutils'
2
3
 
3
4
  begin
4
5
  require_library_or_gem 'fcgi'
@@ -25,4 +26,5 @@ else
25
26
  puts "=> Booting lighttpd (use 'script/server webrick' to force WEBrick)"
26
27
  end
27
28
 
28
- require "commands/servers/#{server}"
29
+ FileUtils.mkdir_p(%w( tmp/sessions tmp/cache tmp/sockets ))
30
+ require "commands/servers/#{server}"
@@ -1,3 +1,5 @@
1
+ require 'rbconfig'
2
+
1
3
  unless RUBY_PLATFORM !~ /mswin/ && !silence_stderr { `lighttpd -version` }.blank?
2
4
  puts "PROBLEM: Lighttpd is not available on your system (or not in your path)"
3
5
  exit 1
@@ -10,15 +12,32 @@ end
10
12
 
11
13
  require 'initializer'
12
14
  configuration = Rails::Initializer.run(:initialize_logger).configuration
15
+ default_config_file = config_file = Pathname.new("#{RAILS_ROOT}/config/lighttpd.conf").cleanpath
16
+
17
+ require 'optparse'
13
18
 
14
- config_file = "#{RAILS_ROOT}/config/lighttpd.conf"
19
+ detach = false
20
+
21
+ ARGV.options do |opt|
22
+ opt.on('-c', "--config=#{config_file}", 'Specify a different lighttpd config file.') { |path| config_file = path }
23
+ opt.on('-h', '--help', 'Show this message.') { puts opt; exit 0 }
24
+ opt.on('-d', '-d', 'Call with -d to detach') { detach = true; puts "=> Configuration in config/lighttpd.conf" }
25
+ opt.parse!
26
+ end
15
27
 
16
28
  unless File.exist?(config_file)
29
+ if config_file != default_config_file
30
+ puts "=> #{config_file} not found."
31
+ exit 1
32
+ end
33
+
17
34
  require 'fileutils'
35
+
18
36
  source = File.expand_path(File.join(File.dirname(__FILE__),
19
37
  "..", "..", "..", "configs", "lighttpd.conf"))
20
38
  puts "=> #{config_file} not found, copying from #{source}"
21
- FileUtils.cp source, config_file
39
+
40
+ FileUtils.cp(source, config_file)
22
41
  end
23
42
 
24
43
  config = IO.read(config_file)
@@ -29,11 +48,8 @@ puts "=> Rails application started on http://#{ip || default_ip}:#{port || defau
29
48
 
30
49
  tail_thread = nil
31
50
 
32
- if ARGV.first == "-d"
33
- puts "=> Configure in config/lighttpd.conf"
34
- detach = true
35
- else
36
- puts "=> Call with -d to detach (requires absolute paths in config/lighttpd.conf)"
51
+ if !detach
52
+ puts "=> Call with -d to detach"
37
53
  puts "=> Ctrl-C to shutdown server (see config/lighttpd.conf for options)"
38
54
  detach = false
39
55
 
@@ -56,5 +72,21 @@ else
56
72
  end
57
73
 
58
74
  trap(:INT) { exit }
59
- `lighttpd #{!detach ? "-D " : ""}-f #{config_file}`
60
- tail_thread.kill if tail_thread
75
+
76
+ begin
77
+ `rake tmp:sockets:clear` # Needed if lighttpd crashes or otherwise leaves FCGI sockets around
78
+ `lighttpd #{!detach ? "-D " : ""}-f #{config_file}`
79
+ ensure
80
+ unless detach
81
+ tail_thread.kill if tail_thread
82
+ puts 'Exiting'
83
+
84
+ # Ensure FCGI processes are reaped
85
+ silence_stream(STDOUT) do
86
+ ARGV.replace ['-a', 'kill']
87
+ require 'commands/process/reaper'
88
+ end
89
+
90
+ `rake tmp:sockets:clear` # Remove sockets on clean shutdown
91
+ end
92
+ end
@@ -0,0 +1,27 @@
1
+ require 'action_controller/integration'
2
+
3
+ # work around the at_exit hook in test/unit, which kills IRB
4
+ Test::Unit.run = true
5
+
6
+ # reference the global "app" instance, created on demand. To recreate the
7
+ # instance, pass a non-false value as the parameter.
8
+ def app(create=false)
9
+ @app_integration_instance = nil if create
10
+ @app_integration_instance ||= new_session do |sess|
11
+ sess.host! "www.example.com"
12
+ end
13
+ end
14
+
15
+ # create a new session. If a block is given, the new session will be yielded
16
+ # to the block before being returned.
17
+ def new_session
18
+ session = ActionController::Integration::Session.new
19
+ yield session if block_given?
20
+ session
21
+ end
22
+
23
+ #reloads the environment
24
+ def reload!
25
+ puts "Reloading..."
26
+ Dispatcher.reset_application!
27
+ end
@@ -0,0 +1,23 @@
1
+ class Module
2
+ def include_all_modules_from(parent_module)
3
+ parent_module.constants.each do |const|
4
+ mod = parent_module.const_get(const)
5
+ if mod.class == Module
6
+ send(:include, mod)
7
+ include_all_modules_from(mod)
8
+ end
9
+ end
10
+ end
11
+ end
12
+
13
+ def helper
14
+ @helper_proxy ||= Object.new
15
+ end
16
+
17
+ require 'application'
18
+
19
+ class << helper
20
+ include_all_modules_from ActionView
21
+ end
22
+
23
+ @controller = ApplicationController.new
@@ -38,7 +38,7 @@ class Dispatcher
38
38
  ActionController::Routing::Routes.recognize!(request).process(request, response).out(output)
39
39
  end
40
40
  rescue Object => exception
41
- failsafe_response(output, '500 Internal Server Error') do
41
+ failsafe_response(output, '500 Internal Server Error', exception) do
42
42
  ActionController::Base.process_with_exception(request, response, exception).out(output)
43
43
  end
44
44
  ensure
@@ -50,11 +50,9 @@ class Dispatcher
50
50
  # mailers, and so forth. This allows them to be loaded again without having
51
51
  # to restart the server (WEBrick, FastCGI, etc.).
52
52
  def reset_application!
53
- Controllers.clear!
54
53
  Dependencies.clear
55
54
  ActiveRecord::Base.reset_subclasses
56
- Dependencies.remove_subclasses_for(ActiveRecord::Base, ActiveRecord::Observer, ActionController::Base)
57
- Dependencies.remove_subclasses_for(ActionMailer::Base) if defined?(ActionMailer::Base)
55
+ Class.remove_class(*Reloadable.reloadable_classes)
58
56
  end
59
57
 
60
58
  private
@@ -68,12 +66,12 @@ class Dispatcher
68
66
  def prepare_application
69
67
  ActionController::Routing::Routes.reload if Dependencies.load?
70
68
  prepare_breakpoint
71
- Controllers.const_load!(:ApplicationController, "application") unless Controllers.const_defined?(:ApplicationController)
69
+ require_dependency('application.rb') unless Object.const_defined?(:ApplicationController)
70
+ ActiveRecord::Base.verify_active_connections!
72
71
  end
73
-
72
+
74
73
  def reset_after_dispatch
75
74
  reset_application! if Dependencies.load?
76
- ActiveRecord::Base.clear_connection_cache!
77
75
  Breakpoint.deactivate_drb if defined?(BREAKPOINT_SERVER_PORT)
78
76
  end
79
77
 
@@ -87,11 +85,13 @@ class Dispatcher
87
85
  end
88
86
 
89
87
  # If the block raises, send status code as a last-ditch response.
90
- def failsafe_response(output, status)
88
+ def failsafe_response(output, status, exception = nil)
91
89
  yield
92
90
  rescue Object
93
91
  begin
94
92
  output.write "Status: #{status}\r\n"
93
+ output.write "Content-Type: text/plain\r\n\r\n"
94
+ output.write exception.to_s + "\r\n" + exception.backtrace.join("\r\n") if exception
95
95
  rescue Object
96
96
  end
97
97
  end
@@ -5,10 +5,11 @@ require 'rbconfig'
5
5
 
6
6
  class RailsFCGIHandler
7
7
  SIGNALS = {
8
- 'HUP' => :reload,
9
- 'TERM' => :exit_now,
10
- 'USR1' => :exit,
11
- 'USR2' => :restart
8
+ 'HUP' => :reload,
9
+ 'TERM' => :exit_now,
10
+ 'USR1' => :exit,
11
+ 'USR2' => :restart,
12
+ 'SIGTRAP' => :breakpoint
12
13
  }
13
14
 
14
15
  attr_reader :when_ready
@@ -61,6 +62,9 @@ class RailsFCGIHandler
61
62
  when :exit
62
63
  close_connection(cgi)
63
64
  break
65
+ when :breakpoint
66
+ close_connection(cgi)
67
+ breakpoint!
64
68
  end
65
69
 
66
70
  gc_countdown
@@ -137,6 +141,11 @@ class RailsFCGIHandler
137
141
  @when_ready = :restart
138
142
  end
139
143
 
144
+ def breakpoint_handler(signal)
145
+ dispatcher_log :info, "asked to breakpoint ASAP"
146
+ @when_ready = :breakpoint
147
+ end
148
+
140
149
  def process_request(cgi)
141
150
  Dispatcher.dispatch(cgi)
142
151
  rescue Object => e
@@ -170,6 +179,15 @@ class RailsFCGIHandler
170
179
  Dispatcher.reset_application!
171
180
  ActionController::Routing::Routes.reload
172
181
  end
182
+
183
+ def breakpoint!
184
+ require 'breakpoint'
185
+ port = defined?(BREAKPOINT_SERVER_PORT) ? BREAKPOINT_SERVER_PORT : 42531
186
+ Breakpoint.activate_drb("druby://localhost:#{port}", nil, !defined?(FastCGI))
187
+ dispatcher_log :info, "breakpointing"
188
+ breakpoint
189
+ @when_ready = nil
190
+ end
173
191
 
174
192
  def run_gc!
175
193
  @gc_request_countdown = gc_request_period
@@ -61,19 +61,20 @@ module Rails
61
61
  # * #initialize_logger
62
62
  # * #initialize_framework_logging
63
63
  # * #initialize_framework_views
64
- # * #initialize_routing
65
64
  # * #initialize_dependency_mechanism
66
65
  # * #initialize_breakpoints
67
66
  # * #initialize_whiny_nils
68
67
  # * #initialize_framework_settings
69
68
  # * #load_environment
70
69
  # * #load_plugins
70
+ # * #initialize_routing
71
71
  #
72
72
  # (Note that #load_environment is invoked twice, once at the start and
73
73
  # once at the end, to support the legacy configuration style where the
74
74
  # environment could overwrite the defaults directly, instead of via the
75
75
  # Configuration instance.
76
76
  def process
77
+ check_ruby_version
77
78
  set_load_path
78
79
  set_connection_adapters
79
80
 
@@ -87,7 +88,8 @@ module Rails
87
88
  initialize_dependency_mechanism
88
89
  initialize_breakpoints
89
90
  initialize_whiny_nils
90
-
91
+ initialize_temporary_directories
92
+
91
93
  initialize_framework_settings
92
94
 
93
95
  # Support for legacy configuration style where the environment
@@ -95,14 +97,24 @@ module Rails
95
97
  # the individual base class configurations.
96
98
  load_environment
97
99
 
98
- load_framework_info
100
+ add_support_load_paths
99
101
 
100
102
  load_plugins
101
103
 
102
104
  # Routing must be initialized after plugins to allow the former to extend the routes
103
105
  initialize_routing
106
+
107
+ # the framework is now fully initialized
108
+ after_initialize
104
109
  end
105
-
110
+
111
+ # Check for valid Ruby version
112
+ # This is done in an external file, so we can use it
113
+ # from the `rails` program as well without duplication.
114
+ def check_ruby_version
115
+ require 'ruby_version_check'
116
+ end
117
+
106
118
  # Set the <tt>$LOAD_PATH</tt> based on the value of
107
119
  # Configuration#load_paths. Duplicates are removed.
108
120
  def set_load_path
@@ -125,10 +137,10 @@ module Rails
125
137
  configuration.frameworks.each { |framework| require(framework.to_s) }
126
138
  end
127
139
 
128
- # Loads Rails::VERSION and Rails::Info.
129
- # TODO: Make this work via dependencies.rb/const_missing instead.
130
- def load_framework_info
131
- require 'rails_info'
140
+ # Add the load paths used by support functions such as the info controller
141
+ def add_support_load_paths
142
+ builtins = File.join(File.dirname(File.dirname(__FILE__)), 'builtin', '*')
143
+ $LOAD_PATH.concat(Dir[builtins])
132
144
  end
133
145
 
134
146
  # Loads all plugins in <tt>config.plugin_paths</tt>. <tt>plugin_paths</tt>
@@ -141,8 +153,9 @@ module Rails
141
153
  # * evaluate <tt>init.rb</tt> if present
142
154
  #
143
155
  # After all plugins are loaded, duplicates are removed from the load path.
156
+ # Plugins are loaded in alphabetical order.
144
157
  def load_plugins
145
- find_plugins(configuration.plugin_paths).each { |path| load_plugin path }
158
+ find_plugins(configuration.plugin_paths).sort.each { |path| load_plugin path }
146
159
  $LOAD_PATH.uniq!
147
160
  end
148
161
 
@@ -224,7 +237,6 @@ module Rails
224
237
  def initialize_routing
225
238
  return unless configuration.frameworks.include?(:action_controller)
226
239
  ActionController::Routing::Routes.reload
227
- Object.const_set "Controllers", Dependencies::LoadingModule.root(*configuration.controller_paths)
228
240
  end
229
241
 
230
242
  # Sets the dependency loading mechanism based on the value of
@@ -245,7 +257,19 @@ module Rails
245
257
  require('active_support/whiny_nil') if configuration.whiny_nils
246
258
  end
247
259
 
248
- # Initialize framework-specific settings for each of the loaded frameworks
260
+ def initialize_temporary_directories
261
+ if configuration.frameworks.include?(:action_controller)
262
+ session_path = "#{RAILS_ROOT}/tmp/sessions/"
263
+ ActionController::Base.session_options[:tmpdir] = File.exist?(session_path) ? session_path : Dir::tmpdir
264
+
265
+ cache_path = "#{RAILS_ROOT}/tmp/cache/"
266
+ if File.exist?(cache_path)
267
+ ActionController::Base.fragment_cache_store = :file_store, cache_path
268
+ end
269
+ end
270
+ end
271
+
272
+ # Initializes framework-specific settings for each of the loaded frameworks
249
273
  # (Configuration#frameworks). The available settings map to the accessors
250
274
  # on each of the corresponding Base classes.
251
275
  def initialize_framework_settings
@@ -257,12 +281,18 @@ module Rails
257
281
  end
258
282
  end
259
283
  end
284
+
285
+ # Fires the user-supplied after_initialize block (Configuration#after_initialize)
286
+ def after_initialize
287
+ configuration.after_initialize_block.call if configuration.after_initialize_block
288
+ end
289
+
260
290
 
261
291
  protected
262
292
  # Return a list of plugin paths within base_path. A plugin path is
263
293
  # a directory that contains either a lib directory or an init.rb file.
264
294
  # This recurses into directories which are not plugin paths, so you
265
- # may organize your plugins which the plugin path.
295
+ # may organize your plugins within the plugin path.
266
296
  def find_plugins(*base_paths)
267
297
  base_paths.flatten.inject([]) do |plugins, base_path|
268
298
  Dir.glob(File.join(base_path, '*')).each do |path|
@@ -301,17 +331,22 @@ module Rails
301
331
  has_lib = File.directory?(lib_path)
302
332
  has_init = File.file?(init_path)
303
333
 
304
- # Add lib to load path.
305
- $LOAD_PATH.unshift(lib_path) if has_lib
306
-
334
+ # Add lib to load path *after* the application lib, to allow
335
+ # application libraries to override plugin libraries.
336
+ if has_lib
337
+ application_lib_index = $LOAD_PATH.index(File.join(RAILS_ROOT, "lib")) || 0
338
+ $LOAD_PATH.insert(application_lib_index + 1, lib_path)
339
+ end
340
+
307
341
  # Allow plugins to reference the current configuration object
308
342
  config = configuration
343
+
344
+ # Add to set of loaded plugins before 'name' collapsed in eval.
345
+ loaded_plugins << name
309
346
 
310
347
  # Evaluate init.rb.
311
348
  silence_warnings { eval(IO.read(init_path), binding, init_path) } if has_init
312
349
 
313
- # Add to set of loaded plugins.
314
- loaded_plugins << name
315
350
  true
316
351
  end
317
352
  end
@@ -435,18 +470,37 @@ module Rails
435
470
  def environment
436
471
  ::RAILS_ENV
437
472
  end
438
-
473
+
474
+ # Sets a block which will be executed after rails has been fully initialized.
475
+ # Useful for per-environment configuration which depends on the framework being
476
+ # fully initialized.
477
+ def after_initialize(&after_initialize_block)
478
+ @after_initialize_block = after_initialize_block
479
+ end
480
+
481
+ # Returns the block set in Configuration#after_initialize
482
+ def after_initialize_block
483
+ @after_initialize_block
484
+ end
485
+
439
486
  private
440
487
  def root_path
441
488
  ::RAILS_ROOT
442
489
  end
443
490
 
491
+ def framework_root_path
492
+ defined?(::RAILS_FRAMEWORK_ROOT) ? ::RAILS_FRAMEWORK_ROOT : "#{root_path}/vendor/rails"
493
+ end
494
+
444
495
  def default_frameworks
445
496
  [ :active_record, :action_controller, :action_view, :action_mailer, :action_web_service ]
446
497
  end
447
498
 
448
499
  def default_load_paths
449
500
  paths = ["#{root_path}/test/mocks/#{environment}"]
501
+
502
+ # Add the app's controller directory
503
+ paths.concat(Dir["#{root_path}/app/controllers/"])
450
504
 
451
505
  # Then model subdirectories.
452
506
  # TODO: Don't include .rb models as load paths
@@ -454,7 +508,6 @@ module Rails
454
508
  paths.concat(Dir["#{root_path}/components/[_a-z]*"])
455
509
 
456
510
  # Followed by the standard includes.
457
- # TODO: Don't include dirs for frameworks that are not used
458
511
  paths.concat %w(
459
512
  app
460
513
  app/models
@@ -466,14 +519,18 @@ module Rails
466
519
  config
467
520
  lib
468
521
  vendor
469
- vendor/rails/railties
470
- vendor/rails/railties/lib
471
- vendor/rails/actionpack/lib
472
- vendor/rails/activesupport/lib
473
- vendor/rails/activerecord/lib
474
- vendor/rails/actionmailer/lib
475
- vendor/rails/actionwebservice/lib
476
522
  ).map { |dir| "#{root_path}/#{dir}" }.select { |dir| File.directory?(dir) }
523
+
524
+ # TODO: Don't include dirs for frameworks that are not used
525
+ paths.concat %w(
526
+ railties
527
+ railties/lib
528
+ actionpack/lib
529
+ activesupport/lib
530
+ activerecord/lib
531
+ actionmailer/lib
532
+ actionwebservice/lib
533
+ ).map { |dir| "#{framework_root_path}/#{dir}" }.select { |dir| File.directory?(dir) }
477
534
  end
478
535
 
479
536
  def default_log_path
@@ -520,10 +577,8 @@ end
520
577
 
521
578
  # Needs to be duplicated from Active Support since its needed before Active
522
579
  # Support is available.
523
- class OrderedOptions < Array # :nodoc:
524
- def []=(key, value)
525
- key = key.to_sym
526
-
580
+ class OrderedHash < Array #:nodoc:
581
+ def []=(key, value)
527
582
  if pair = find_pair(key)
528
583
  pair.pop
529
584
  pair << value
@@ -531,18 +586,14 @@ class OrderedOptions < Array # :nodoc:
531
586
  self << [key, value]
532
587
  end
533
588
  end
534
-
589
+
535
590
  def [](key)
536
- pair = find_pair(key.to_sym)
591
+ pair = find_pair(key)
537
592
  pair ? pair.last : nil
538
593
  end
539
594
 
540
- def method_missing(name, *args)
541
- if name.to_s =~ /(.*)=$/
542
- self[$1.to_sym] = args.first
543
- else
544
- self[name]
545
- end
595
+ def keys
596
+ self.collect { |i| i.first }
546
597
  end
547
598
 
548
599
  private
@@ -551,3 +602,21 @@ class OrderedOptions < Array # :nodoc:
551
602
  return false
552
603
  end
553
604
  end
605
+
606
+ class OrderedOptions < OrderedHash #:nodoc:
607
+ def []=(key, value)
608
+ super(key.to_sym, value)
609
+ end
610
+
611
+ def [](key)
612
+ super(key.to_sym)
613
+ end
614
+
615
+ def method_missing(name, *args)
616
+ if name.to_s =~ /(.*)=$/
617
+ self[$1.to_sym] = args.first
618
+ else
619
+ self[name]
620
+ end
621
+ end
622
+ end