rails 1.0.0 → 2.0.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 (177) hide show
  1. data/CHANGELOG +1020 -10
  2. data/MIT-LICENSE +1 -1
  3. data/README +110 -60
  4. data/Rakefile +74 -139
  5. data/bin/about +1 -1
  6. data/bin/console +1 -1
  7. data/bin/destroy +1 -1
  8. data/bin/generate +1 -1
  9. data/bin/performance/request +3 -0
  10. data/bin/plugin +1 -1
  11. data/bin/process/{spinner → inspector} +1 -1
  12. data/bin/rails +10 -12
  13. data/bin/runner +1 -1
  14. data/bin/server +1 -1
  15. data/{lib/rails_info.rb → builtin/rails_info/rails/info.rb} +33 -14
  16. data/builtin/rails_info/rails/info_controller.rb +9 -0
  17. data/builtin/rails_info/rails/info_helper.rb +2 -0
  18. data/builtin/rails_info/rails_info_controller.rb +2 -0
  19. data/configs/apache.conf +1 -1
  20. data/configs/databases/frontbase.yml +28 -0
  21. data/configs/databases/mysql.yml +54 -0
  22. data/configs/databases/oracle.yml +39 -0
  23. data/configs/databases/postgresql.yml +48 -0
  24. data/configs/databases/sqlite2.yml +16 -0
  25. data/configs/databases/sqlite3.yml +19 -0
  26. data/configs/initializers/inflections.rb +10 -0
  27. data/configs/initializers/mime_types.rb +5 -0
  28. data/configs/lighttpd.conf +29 -15
  29. data/configs/routes.rb +27 -11
  30. data/doc/README_FOR_APP +1 -1
  31. data/environments/boot.rb +103 -14
  32. data/environments/development.rb +5 -6
  33. data/environments/environment.rb +36 -30
  34. data/environments/production.rb +2 -3
  35. data/environments/test.rb +5 -2
  36. data/fresh_rakefile +2 -2
  37. data/helpers/application.rb +8 -2
  38. data/helpers/test_helper.rb +10 -0
  39. data/html/404.html +27 -5
  40. data/html/422.html +30 -0
  41. data/html/500.html +27 -5
  42. data/html/index.html +6 -6
  43. data/html/javascripts/application.js +2 -0
  44. data/html/javascripts/controls.js +532 -319
  45. data/html/javascripts/dragdrop.js +521 -133
  46. data/html/javascripts/effects.js +708 -442
  47. data/html/javascripts/prototype.js +3393 -953
  48. data/html/robots.txt +5 -1
  49. data/lib/code_statistics.rb +2 -2
  50. data/lib/commands/console.rb +18 -9
  51. data/lib/commands/performance/profiler.rb +25 -9
  52. data/lib/commands/performance/request.rb +6 -0
  53. data/lib/commands/plugin.rb +196 -96
  54. data/lib/commands/process/inspector.rb +68 -0
  55. data/lib/commands/process/reaper.rb +90 -71
  56. data/lib/commands/process/spawner.rb +188 -21
  57. data/lib/commands/process/spinner.rb +3 -3
  58. data/lib/commands/runner.rb +28 -7
  59. data/lib/commands/server.rb +20 -9
  60. data/lib/commands/servers/base.rb +31 -0
  61. data/lib/commands/servers/lighttpd.rb +60 -26
  62. data/lib/commands/servers/mongrel.rb +69 -0
  63. data/lib/commands/servers/webrick.rb +18 -11
  64. data/lib/console_app.rb +30 -0
  65. data/lib/console_sandbox.rb +2 -2
  66. data/lib/console_with_helpers.rb +26 -0
  67. data/lib/dispatcher.rb +3 -78
  68. data/lib/fcgi_handler.rb +98 -64
  69. data/lib/initializer.rb +323 -194
  70. data/lib/rails/plugin/loader.rb +150 -0
  71. data/lib/rails/plugin/locator.rb +78 -0
  72. data/lib/rails/plugin.rb +84 -0
  73. data/lib/{rails_version.rb → rails/version.rb} +1 -1
  74. data/lib/rails_generator/base.rb +85 -25
  75. data/lib/rails_generator/commands.rb +122 -40
  76. data/lib/rails_generator/generated_attribute.rb +42 -0
  77. data/lib/rails_generator/generators/applications/app/USAGE +0 -7
  78. data/lib/rails_generator/generators/applications/app/app_generator.rb +67 -28
  79. data/lib/rails_generator/generators/components/controller/USAGE +11 -12
  80. data/lib/rails_generator/generators/components/controller/controller_generator.rb +2 -3
  81. data/lib/rails_generator/generators/components/controller/templates/functional_test.rb +1 -11
  82. data/lib/rails_generator/generators/components/controller/templates/{view.rhtml → view.html.erb} +0 -0
  83. data/lib/rails_generator/generators/components/integration_test/USAGE +8 -0
  84. data/lib/rails_generator/generators/components/integration_test/integration_test_generator.rb +16 -0
  85. data/lib/rails_generator/generators/components/integration_test/templates/integration_test.rb +10 -0
  86. data/lib/rails_generator/generators/components/mailer/USAGE +9 -11
  87. data/lib/rails_generator/generators/components/mailer/mailer_generator.rb +10 -8
  88. data/lib/rails_generator/generators/components/mailer/templates/fixture.erb +3 -0
  89. data/lib/rails_generator/generators/components/mailer/templates/fixture.rhtml +0 -3
  90. data/lib/rails_generator/generators/components/mailer/templates/unit_test.rb +9 -25
  91. data/lib/rails_generator/generators/components/mailer/templates/view.erb +3 -0
  92. data/lib/rails_generator/generators/components/mailer/templates/view.rhtml +0 -3
  93. data/lib/rails_generator/generators/components/migration/USAGE +23 -8
  94. data/lib/rails_generator/generators/components/migration/migration_generator.rb +15 -2
  95. data/lib/rails_generator/generators/components/migration/templates/migration.rb +7 -3
  96. data/lib/rails_generator/generators/components/model/USAGE +21 -11
  97. data/lib/rails_generator/generators/components/model/model_generator.rb +28 -1
  98. data/lib/rails_generator/generators/components/model/templates/fixtures.yml +18 -4
  99. data/lib/rails_generator/generators/components/model/templates/migration.rb +16 -0
  100. data/lib/rails_generator/generators/components/model/templates/unit_test.rb +2 -4
  101. data/lib/rails_generator/generators/components/observer/USAGE +13 -0
  102. data/lib/rails_generator/generators/components/observer/observer_generator.rb +16 -0
  103. data/lib/rails_generator/generators/components/observer/templates/observer.rb +2 -0
  104. data/lib/rails_generator/generators/components/observer/templates/unit_test.rb +8 -0
  105. data/lib/rails_generator/generators/components/plugin/USAGE +10 -18
  106. data/lib/rails_generator/generators/components/plugin/plugin_generator.rb +6 -0
  107. data/lib/rails_generator/generators/components/plugin/templates/MIT-LICENSE +20 -0
  108. data/lib/rails_generator/generators/components/plugin/templates/README +10 -1
  109. data/lib/rails_generator/generators/components/plugin/templates/Rakefile +1 -1
  110. data/lib/rails_generator/generators/components/plugin/templates/USAGE +1 -1
  111. data/lib/rails_generator/generators/components/plugin/templates/init.rb +1 -1
  112. data/lib/rails_generator/generators/components/plugin/templates/install.rb +1 -0
  113. data/lib/rails_generator/generators/components/plugin/templates/plugin.rb +1 -1
  114. data/lib/rails_generator/generators/components/plugin/templates/tasks.rake +1 -1
  115. data/lib/rails_generator/generators/components/plugin/templates/uninstall.rb +1 -0
  116. data/lib/rails_generator/generators/components/resource/USAGE +23 -0
  117. data/lib/rails_generator/generators/components/resource/resource_generator.rb +74 -0
  118. data/lib/rails_generator/generators/components/resource/templates/controller.rb +2 -0
  119. data/lib/rails_generator/generators/components/resource/templates/functional_test.rb +8 -0
  120. data/lib/rails_generator/generators/components/resource/templates/helper.rb +2 -0
  121. data/lib/rails_generator/generators/components/scaffold/USAGE +24 -31
  122. data/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb +45 -137
  123. data/lib/rails_generator/generators/components/scaffold/templates/controller.rb +65 -34
  124. data/lib/rails_generator/generators/components/scaffold/templates/functional_test.rb +23 -76
  125. data/lib/rails_generator/generators/components/scaffold/templates/layout.html.erb +17 -0
  126. data/lib/rails_generator/generators/components/scaffold/templates/style.css +5 -5
  127. data/lib/rails_generator/generators/components/scaffold/templates/view_edit.html.erb +19 -0
  128. data/lib/rails_generator/generators/components/scaffold/templates/view_index.html.erb +24 -0
  129. data/lib/rails_generator/generators/components/scaffold/templates/view_new.html.erb +18 -0
  130. data/lib/rails_generator/generators/components/scaffold/templates/view_show.html.erb +10 -0
  131. data/lib/rails_generator/generators/components/session_migration/USAGE +6 -11
  132. data/lib/rails_generator/generators/components/session_migration/session_migration_generator.rb +7 -1
  133. data/lib/rails_generator/generators/components/session_migration/templates/migration.rb +8 -7
  134. data/lib/rails_generator/lookup.rb +46 -12
  135. data/lib/rails_generator/options.rb +11 -8
  136. data/lib/rails_generator/scripts/destroy.rb +23 -0
  137. data/lib/rails_generator/scripts.rb +7 -4
  138. data/lib/rails_generator/secret_key_generator.rb +160 -0
  139. data/lib/rails_generator/spec.rb +1 -1
  140. data/lib/rails_generator.rb +1 -1
  141. data/lib/railties_path.rb +1 -1
  142. data/lib/ruby_version_check.rb +17 -0
  143. data/lib/source_annotation_extractor.rb +62 -0
  144. data/lib/tasks/annotations.rake +23 -0
  145. data/lib/tasks/databases.rake +328 -133
  146. data/lib/tasks/documentation.rake +72 -68
  147. data/lib/tasks/framework.rake +99 -58
  148. data/lib/tasks/log.rake +9 -0
  149. data/lib/tasks/misc.rake +2 -17
  150. data/lib/tasks/rails.rb +2 -2
  151. data/lib/tasks/routes.rake +17 -0
  152. data/lib/tasks/statistics.rake +10 -8
  153. data/lib/tasks/testing.rake +99 -31
  154. data/lib/tasks/tmp.rake +37 -0
  155. data/lib/test_help.rb +8 -5
  156. data/lib/webrick_server.rb +11 -16
  157. metadata +312 -272
  158. data/bin/breakpointer +0 -3
  159. data/builtin/controllers/rails_info_controller.rb +0 -11
  160. data/configs/database.yml +0 -85
  161. data/lib/binding_of_caller.rb +0 -85
  162. data/lib/breakpoint.rb +0 -523
  163. data/lib/breakpoint_client.rb +0 -196
  164. data/lib/commands/breakpointer.rb +0 -1
  165. data/lib/rails_generator/generators/components/scaffold/templates/form.rhtml +0 -3
  166. data/lib/rails_generator/generators/components/scaffold/templates/form_scaffolding.rhtml +0 -1
  167. data/lib/rails_generator/generators/components/scaffold/templates/layout.rhtml +0 -13
  168. data/lib/rails_generator/generators/components/scaffold/templates/view_edit.rhtml +0 -9
  169. data/lib/rails_generator/generators/components/scaffold/templates/view_list.rhtml +0 -27
  170. data/lib/rails_generator/generators/components/scaffold/templates/view_new.rhtml +0 -8
  171. data/lib/rails_generator/generators/components/scaffold/templates/view_show.rhtml +0 -8
  172. data/lib/rails_generator/generators/components/web_service/USAGE +0 -28
  173. data/lib/rails_generator/generators/components/web_service/templates/api_definition.rb +0 -5
  174. data/lib/rails_generator/generators/components/web_service/templates/controller.rb +0 -8
  175. data/lib/rails_generator/generators/components/web_service/templates/functional_test.rb +0 -19
  176. data/lib/rails_generator/generators/components/web_service/web_service_generator.rb +0 -29
  177. data/lib/tasks/javascripts.rake +0 -6
@@ -1,3 +1,6 @@
1
+ require 'rbconfig'
2
+ require 'commands/servers/base'
3
+
1
4
  unless RUBY_PLATFORM !~ /mswin/ && !silence_stderr { `lighttpd -version` }.blank?
2
5
  puts "PROBLEM: Lighttpd is not available on your system (or not in your path)"
3
6
  exit 1
@@ -10,51 +13,82 @@ end
10
13
 
11
14
  require 'initializer'
12
15
  configuration = Rails::Initializer.run(:initialize_logger).configuration
16
+ default_config_file = config_file = Pathname.new("#{RAILS_ROOT}/config/lighttpd.conf").cleanpath
17
+
18
+ require 'optparse'
13
19
 
14
- config_file = "#{RAILS_ROOT}/config/lighttpd.conf"
20
+ detach = false
21
+ command_line_port = nil
22
+
23
+ ARGV.options do |opt|
24
+ opt.on("-p", "--port=port", "Changes the server.port number in the config/lighttpd.conf") { |port| command_line_port = port }
25
+ opt.on('-c', "--config=#{config_file}", 'Specify a different lighttpd config file.') { |path| config_file = path }
26
+ opt.on('-h', '--help', 'Show this message.') { puts opt; exit 0 }
27
+ opt.on('-d', '-d', 'Call with -d to detach') { detach = true; puts "=> Configuration in config/lighttpd.conf" }
28
+ opt.parse!
29
+ end
15
30
 
16
31
  unless File.exist?(config_file)
32
+ if config_file != default_config_file
33
+ puts "=> #{config_file} not found."
34
+ exit 1
35
+ end
36
+
17
37
  require 'fileutils'
38
+
18
39
  source = File.expand_path(File.join(File.dirname(__FILE__),
19
40
  "..", "..", "..", "configs", "lighttpd.conf"))
20
41
  puts "=> #{config_file} not found, copying from #{source}"
21
- FileUtils.cp source, config_file
42
+
43
+ FileUtils.cp(source, config_file)
44
+ end
45
+
46
+ # open the config/lighttpd.conf file and add the current user defined port setting to it
47
+ if command_line_port
48
+ File.open(config_file, 'r+') do |config|
49
+ lines = config.readlines
50
+
51
+ lines.each do |line|
52
+ line.gsub!(/^\s*server.port\s*=\s*(\d+)/, "server.port = #{command_line_port}")
53
+ end
54
+
55
+ config.rewind
56
+ config.print(lines)
57
+ config.truncate(config.pos)
58
+ end
22
59
  end
23
60
 
24
61
  config = IO.read(config_file)
25
62
  default_port, default_ip = 3000, '0.0.0.0'
26
63
  port = config.scan(/^\s*server.port\s*=\s*(\d+)/).first rescue default_port
27
64
  ip = config.scan(/^\s*server.bind\s*=\s*"([^"]+)"/).first rescue default_ip
28
- puts "=> Rails application started on http://#{ip || default_ip}:#{port || default_port}"
65
+ puts "=> Rails application starting on http://#{ip || default_ip}:#{port || default_port}"
29
66
 
30
67
  tail_thread = nil
31
68
 
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)"
69
+ if !detach
70
+ puts "=> Call with -d to detach"
37
71
  puts "=> Ctrl-C to shutdown server (see config/lighttpd.conf for options)"
38
72
  detach = false
73
+ tail_thread = tail(configuration.log_path)
74
+ end
39
75
 
40
- cursor = File.size(configuration.log_path)
41
- last_checked = Time.now
42
- tail_thread = Thread.new do
43
- File.open(configuration.log_path, 'r') do |f|
44
- loop do
45
- f.seek cursor
46
- if f.mtime > last_checked
47
- last_checked = f.mtime
48
- contents = f.read
49
- cursor += contents.length
50
- print contents
51
- end
52
- sleep 1
53
- end
76
+ trap(:INT) { exit }
77
+
78
+ begin
79
+ `rake tmp:sockets:clear` # Needed if lighttpd crashes or otherwise leaves FCGI sockets around
80
+ `lighttpd #{!detach ? "-D " : ""}-f #{config_file}`
81
+ ensure
82
+ unless detach
83
+ tail_thread.kill if tail_thread
84
+ puts 'Exiting'
85
+
86
+ # Ensure FCGI processes are reaped
87
+ silence_stream(STDOUT) do
88
+ ARGV.replace ['-a', 'kill']
89
+ require 'commands/process/reaper'
54
90
  end
91
+
92
+ `rake tmp:sockets:clear` # Remove sockets on clean shutdown
55
93
  end
56
94
  end
57
-
58
- trap(:INT) { exit }
59
- `lighttpd #{!detach ? "-D " : ""}-f #{config_file}`
60
- tail_thread.kill if tail_thread
@@ -0,0 +1,69 @@
1
+ require 'rbconfig'
2
+ require 'commands/servers/base'
3
+
4
+ unless defined?(Mongrel)
5
+ puts "PROBLEM: Mongrel is not available on your system (or not in your path)"
6
+ exit 1
7
+ end
8
+
9
+ require 'optparse'
10
+
11
+ OPTIONS = {
12
+ :port => 3000,
13
+ :ip => "0.0.0.0",
14
+ :environment => (ENV['RAILS_ENV'] || "development").dup,
15
+ :detach => false,
16
+ :debugger => false
17
+ }
18
+
19
+ ARGV.clone.options do |opts|
20
+ opts.on("-p", "--port=port", Integer, "Runs Rails on the specified port.", "Default: 3000") { |v| OPTIONS[:port] = v }
21
+ opts.on("-b", "--binding=ip", String, "Binds Rails to the specified ip.", "Default: 0.0.0.0") { |v| OPTIONS[:ip] = v }
22
+ opts.on("-d", "--daemon", "Make server run as a Daemon.") { OPTIONS[:detach] = true }
23
+ opts.on("-u", "--debugger", "Enable ruby-debugging for the server.") { OPTIONS[:debugger] = true }
24
+ opts.on("-e", "--environment=name", String,
25
+ "Specifies the environment to run this server under (test/development/production).",
26
+ "Default: development") { |v| OPTIONS[:environment] = v }
27
+
28
+ opts.separator ""
29
+
30
+ opts.on("-h", "--help", "Show this help message.") { puts opts; exit }
31
+
32
+ opts.parse!
33
+ end
34
+
35
+ puts "=> Rails application starting on http://#{OPTIONS[:ip]}:#{OPTIONS[:port]}"
36
+
37
+ parameters = [
38
+ "start",
39
+ "-p", OPTIONS[:port].to_s,
40
+ "-a", OPTIONS[:ip].to_s,
41
+ "-e", OPTIONS[:environment],
42
+ "-P", "#{RAILS_ROOT}/tmp/pids/mongrel.pid"
43
+ ]
44
+
45
+ if OPTIONS[:detach]
46
+ `mongrel_rails #{parameters.join(" ")} -d`
47
+ else
48
+ ENV["RAILS_ENV"] = OPTIONS[:environment]
49
+ RAILS_ENV.replace(OPTIONS[:environment]) if defined?(RAILS_ENV)
50
+
51
+ start_debugger if OPTIONS[:debugger]
52
+
53
+ require 'initializer'
54
+ Rails::Initializer.run(:initialize_logger)
55
+
56
+ puts "=> Call with -d to detach"
57
+ puts "=> Ctrl-C to shutdown server"
58
+ tail_thread = tail(Pathname.new("#{File.expand_path(RAILS_ROOT)}/log/#{RAILS_ENV}.log").cleanpath)
59
+
60
+ trap(:INT) { exit }
61
+
62
+ begin
63
+ silence_warnings { ARGV = parameters }
64
+ load("mongrel_rails")
65
+ ensure
66
+ tail_thread.kill if tail_thread
67
+ puts 'Exiting'
68
+ end
69
+ end
@@ -1,14 +1,17 @@
1
1
  require 'webrick'
2
2
  require 'optparse'
3
+ require 'commands/servers/base'
3
4
 
4
5
  OPTIONS = {
5
- :port => 3000,
6
- :ip => "0.0.0.0",
7
- :environment => (ENV['RAILS_ENV'] || "development").dup,
8
- :server_root => File.expand_path(RAILS_ROOT + "/public/"),
9
- :server_type => WEBrick::SimpleServer,
10
- :charset => "UTF-8",
11
- :mime_types => WEBrick::HTTPUtils::DefaultMimeTypes
6
+ :port => 3000,
7
+ :ip => "0.0.0.0",
8
+ :environment => (ENV['RAILS_ENV'] || "development").dup,
9
+ :server_root => File.expand_path(RAILS_ROOT + "/public/"),
10
+ :server_type => WEBrick::SimpleServer,
11
+ :charset => "UTF-8",
12
+ :mime_types => WEBrick::HTTPUtils::DefaultMimeTypes,
13
+ :debugger => false
14
+
12
15
  }
13
16
 
14
17
  ARGV.options do |opts|
@@ -19,13 +22,13 @@ ARGV.options do |opts|
19
22
 
20
23
  opts.on("-p", "--port=port", Integer,
21
24
  "Runs Rails on the specified port.",
22
- "Default: 3000") { |OPTIONS[:port]| }
25
+ "Default: 3000") { |v| OPTIONS[:port] = v }
23
26
  opts.on("-b", "--binding=ip", String,
24
27
  "Binds Rails to the specified ip.",
25
- "Default: 0.0.0.0") { |OPTIONS[:ip]| }
28
+ "Default: 0.0.0.0") { |v| OPTIONS[:ip] = v }
26
29
  opts.on("-e", "--environment=name", String,
27
30
  "Specifies the environment to run this server under (test/development/production).",
28
- "Default: development") { |OPTIONS[:environment]| }
31
+ "Default: development") { |v| OPTIONS[:environment] = v }
29
32
  opts.on("-m", "--mime-types=filename", String,
30
33
  "Specifies an Apache style mime.types configuration file to be used for mime types",
31
34
  "Default: none") { |mime_types_file| OPTIONS[:mime_types] = WEBrick::HTTPUtils::load_mime_types(mime_types_file) }
@@ -34,9 +37,11 @@ ARGV.options do |opts|
34
37
  "Make Rails run as a Daemon (only works if fork is available -- meaning on *nix)."
35
38
  ) { OPTIONS[:server_type] = WEBrick::Daemon }
36
39
 
40
+ opts.on("-u", "--debugger", "Enable ruby-debugging for the server.") { OPTIONS[:debugger] = true }
41
+
37
42
  opts.on("-c", "--charset=charset", String,
38
43
  "Set default charset for output.",
39
- "Default: UTF-8") { |OPTIONS[:charset]| }
44
+ "Default: UTF-8") { |v| OPTIONS[:charset] = v }
40
45
 
41
46
  opts.separator ""
42
47
 
@@ -46,6 +51,8 @@ ARGV.options do |opts|
46
51
  opts.parse!
47
52
  end
48
53
 
54
+ start_debugger if OPTIONS[:debugger]
55
+
49
56
  ENV["RAILS_ENV"] = OPTIONS[:environment]
50
57
  RAILS_ENV.replace(OPTIONS[:environment]) if defined?(RAILS_ENV)
51
58
 
@@ -0,0 +1,30 @@
1
+ require 'action_controller/integration'
2
+
3
+ # work around the at_exit hook in test/unit, which kills IRB
4
+ Test::Unit.run = true if Test::Unit.respond_to?(:run=)
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 = ActionController::Dispatcher.new($stdout)
27
+ dispatcher.cleanup_application(true)
28
+ dispatcher.prepare_application(true)
29
+ true
30
+ end
@@ -1,6 +1,6 @@
1
- ActiveRecord::Base.lock_mutex
1
+ ActiveRecord::Base.send :increment_open_transactions
2
2
  ActiveRecord::Base.connection.begin_db_transaction
3
3
  at_exit do
4
4
  ActiveRecord::Base.connection.rollback_db_transaction
5
- ActiveRecord::Base.unlock_mutex
5
+ ActiveRecord::Base.send :decrement_open_transactions
6
6
  end
@@ -0,0 +1,26 @@
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(*helper_names)
14
+ returning @helper_proxy ||= Object.new do |helper|
15
+ helper_names.each { |h| helper.extend "#{h}_helper".classify.constantize }
16
+ end
17
+ end
18
+
19
+ require 'application'
20
+
21
+ class << helper
22
+ include_all_modules_from ActionView
23
+ end
24
+
25
+ @controller = ApplicationController.new
26
+ helper :application rescue nil
data/lib/dispatcher.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2004 David Heinemeier Hansson
2
+ # Copyright (c) 2004-2007 David Heinemeier Hansson
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining
5
5
  # a copy of this software and associated documentation files (the
@@ -20,80 +20,5 @@
20
20
  # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
21
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
22
  #++
23
-
24
- # This class provides an interface for dispatching a CGI (or CGI-like) request
25
- # to the appropriate controller and action. It also takes care of resetting
26
- # the environment (when Dependencies.load? is true) after each request.
27
- class Dispatcher
28
- class << self
29
-
30
- # Dispatch the given CGI request, using the given session options, and
31
- # emitting the output via the given output. If you dispatch with your
32
- # own CGI object be sure to handle the exceptions it raises on multipart
33
- # requests (EOFError and ArgumentError).
34
- def dispatch(cgi = nil, session_options = ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS, output = $stdout)
35
- if cgi ||= new_cgi(output)
36
- request, response = ActionController::CgiRequest.new(cgi, session_options), ActionController::CgiResponse.new(cgi)
37
- prepare_application
38
- ActionController::Routing::Routes.recognize!(request).process(request, response).out(output)
39
- end
40
- rescue Object => exception
41
- failsafe_response(output, '500 Internal Server Error') do
42
- ActionController::Base.process_with_exception(request, response, exception).out(output)
43
- end
44
- ensure
45
- # Do not give a failsafe response here.
46
- reset_after_dispatch
47
- end
48
-
49
- # Reset the application by clearing out loaded controllers, views, actions,
50
- # mailers, and so forth. This allows them to be loaded again without having
51
- # to restart the server (WEBrick, FastCGI, etc.).
52
- def reset_application!
53
- Controllers.clear!
54
- Dependencies.clear
55
- 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)
58
- end
59
-
60
- private
61
- # CGI.new plus exception handling. CGI#read_multipart raises EOFError
62
- # if body.empty? or body.size != Content-Length and raises ArgumentError
63
- # if Content-Length is non-integer.
64
- def new_cgi(output)
65
- failsafe_response(output, '400 Bad Request') { CGI.new }
66
- end
67
-
68
- def prepare_application
69
- ActionController::Routing::Routes.reload if Dependencies.load?
70
- prepare_breakpoint
71
- Controllers.const_load!(:ApplicationController, "application") unless Controllers.const_defined?(:ApplicationController)
72
- end
73
-
74
- def reset_after_dispatch
75
- reset_application! if Dependencies.load?
76
- ActiveRecord::Base.clear_connection_cache!
77
- Breakpoint.deactivate_drb if defined?(BREAKPOINT_SERVER_PORT)
78
- end
79
-
80
- def prepare_breakpoint
81
- return unless defined?(BREAKPOINT_SERVER_PORT)
82
- require 'breakpoint'
83
- Breakpoint.activate_drb("druby://localhost:#{BREAKPOINT_SERVER_PORT}", nil, !defined?(FastCGI))
84
- true
85
- rescue
86
- nil
87
- end
88
-
89
- # If the block raises, send status code as a last-ditch response.
90
- def failsafe_response(output, status)
91
- yield
92
- rescue Object
93
- begin
94
- output.write "Status: #{status}\r\n"
95
- rescue Object
96
- end
97
- end
98
- end
99
- end
23
+ require 'action_controller/dispatcher'
24
+ Dispatcher = ActionController::Dispatcher
data/lib/fcgi_handler.rb CHANGED
@@ -5,11 +5,13 @@ 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
+ 'INT' => :exit_now,
10
+ 'TERM' => :exit_now,
11
+ 'USR1' => :exit,
12
+ 'USR2' => :restart
12
13
  }
14
+ GLOBAL_SIGNALS = SIGNALS.keys - %w(USR1)
13
15
 
14
16
  attr_reader :when_ready
15
17
 
@@ -39,53 +41,72 @@ class RailsFCGIHandler
39
41
 
40
42
  # Start error timestamp at 11 seconds ago.
41
43
  @last_error_on = Time.now - 11
42
-
43
- dispatcher_log :info, "starting"
44
44
  end
45
45
 
46
46
  def process!(provider = FCGI)
47
- # Make a note of $" so we can safely reload this instance.
48
- mark!
49
-
50
- run_gc! if gc_request_period
51
-
52
- provider.each_cgi do |cgi|
53
- process_request(cgi)
54
-
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
47
+ mark_features!
48
+
49
+ dispatcher_log :info, 'starting'
50
+ process_each_request provider
51
+ dispatcher_log :info, 'stopping gracefully'
52
+
53
+ rescue Exception => error
54
+ case error
55
+ when SystemExit
56
+ dispatcher_log :info, 'stopping after explicit exit'
57
+ when SignalException
58
+ dispatcher_error error, 'stopping after unhandled signal'
59
+ else
60
+ # Retry if exceptions occur more than 10 seconds apart.
61
+ if Time.now - @last_error_on > 10
62
+ @last_error_on = Time.now
63
+ dispatcher_error error, 'retrying after unhandled exception'
64
+ retry
65
+ else
66
+ dispatcher_error error, 'stopping after unhandled exception within 10 seconds of the last'
64
67
  end
65
-
66
- gc_countdown
67
68
  end
69
+ end
68
70
 
69
- GC.enable
70
- dispatcher_log :info, "terminated gracefully"
71
71
 
72
- rescue SystemExit => exit_error
73
- dispatcher_log :info, "terminated by explicit exit"
72
+ protected
73
+ def process_each_request(provider)
74
+ cgi = nil
74
75
 
75
- rescue Object => fcgi_error
76
- # retry on errors that would otherwise have terminated the FCGI process,
77
- # but only if they occur more than 10 seconds apart.
78
- if !(SignalException === fcgi_error) && Time.now - @last_error_on > 10
79
- @last_error_on = Time.now
80
- dispatcher_error(fcgi_error, "almost killed by this error")
81
- retry
82
- else
83
- dispatcher_error(fcgi_error, "killed by this error")
76
+ provider.each_cgi do |cgi|
77
+ process_request(cgi)
78
+
79
+ case when_ready
80
+ when :reload
81
+ reload!
82
+ when :restart
83
+ close_connection(cgi)
84
+ restart!
85
+ when :exit
86
+ close_connection(cgi)
87
+ break
88
+ end
89
+ end
90
+ rescue SignalException => signal
91
+ raise unless signal.message == 'SIGUSR1'
92
+ close_connection(cgi)
84
93
  end
85
- end
86
-
87
-
88
- private
94
+
95
+ def process_request(cgi)
96
+ @when_ready = nil
97
+ gc_countdown
98
+
99
+ with_signal_handler 'USR1' do
100
+ begin
101
+ Dispatcher.dispatch(cgi)
102
+ rescue SignalException, SystemExit
103
+ raise
104
+ rescue Exception => error
105
+ dispatcher_error error, 'unhandled dispatch error'
106
+ end
107
+ end
108
+ end
109
+
89
110
  def logger
90
111
  @logger ||= Logger.new(@log_file_path)
91
112
  end
@@ -93,7 +114,7 @@ class RailsFCGIHandler
93
114
  def dispatcher_log(level, msg)
94
115
  time_str = Time.now.strftime("%d/%b/%Y:%H:%M:%S")
95
116
  logger.send(level, "[#{time_str} :: #{$$}] #{msg}")
96
- rescue Object => log_error
117
+ rescue Exception => log_error # Logger errors
97
118
  STDERR << "Couldn't write to #{@log_file_path.inspect}: #{msg}\n"
98
119
  STDERR << " #{log_error.class}: #{log_error.message}\n"
99
120
  end
@@ -106,24 +127,37 @@ class RailsFCGIHandler
106
127
  end
107
128
 
108
129
  def install_signal_handlers
109
- SIGNALS.each do |signal, handler_name|
110
- install_signal_handler(signal, method("#{handler_name}_handler").to_proc)
130
+ GLOBAL_SIGNALS.each { |signal| install_signal_handler(signal) }
131
+ end
132
+
133
+ def install_signal_handler(signal, handler = nil)
134
+ if SIGNALS.include?(signal) && self.class.method_defined?(name = "#{SIGNALS[signal]}_handler")
135
+ handler ||= method(name).to_proc
136
+
137
+ begin
138
+ trap(signal, handler)
139
+ rescue ArgumentError
140
+ dispatcher_log :warn, "Ignoring unsupported signal #{signal}."
141
+ end
142
+ else
143
+ dispatcher_log :warn, "Ignoring unsupported signal #{signal}."
111
144
  end
112
145
  end
113
146
 
114
- def install_signal_handler(signal, handler)
115
- trap(signal, handler)
116
- rescue ArgumentError
117
- dispatcher_log :warn, "Ignoring unsupported signal #{signal}."
147
+ def with_signal_handler(signal)
148
+ install_signal_handler(signal)
149
+ yield
150
+ ensure
151
+ install_signal_handler(signal, 'DEFAULT')
118
152
  end
119
153
 
120
154
  def exit_now_handler(signal)
121
- dispatcher_log :info, "asked to terminate immediately"
155
+ dispatcher_log :info, "asked to stop immediately"
122
156
  exit
123
157
  end
124
158
 
125
159
  def exit_handler(signal)
126
- dispatcher_log :info, "asked to terminate ASAP"
160
+ dispatcher_log :info, "asked to stop ASAP"
127
161
  @when_ready = :exit
128
162
  end
129
163
 
@@ -137,20 +171,18 @@ class RailsFCGIHandler
137
171
  @when_ready = :restart
138
172
  end
139
173
 
140
- def process_request(cgi)
141
- Dispatcher.dispatch(cgi)
142
- rescue Object => e
143
- raise if SignalException === e
144
- dispatcher_error(e)
145
- end
146
-
147
174
  def restart!
148
175
  config = ::Config::CONFIG
149
176
  ruby = File::join(config['bindir'], config['ruby_install_name']) + config['EXEEXT']
150
177
  command_line = [ruby, $0, ARGV].flatten.join(' ')
151
-
178
+
152
179
  dispatcher_log :info, "restarted"
153
180
 
181
+ # close resources as they won't be closed by
182
+ # the OS when using exec
183
+ logger.close rescue nil
184
+ RAILS_DEFAULT_LOGGER.close rescue nil
185
+
154
186
  exec(command_line)
155
187
  end
156
188
 
@@ -161,7 +193,8 @@ class RailsFCGIHandler
161
193
  dispatcher_log :info, "reloaded"
162
194
  end
163
195
 
164
- def mark!
196
+ # Make a note of $" so we can safely reload this instance.
197
+ def mark_features!
165
198
  @features = $".clone
166
199
  end
167
200
 
@@ -175,15 +208,16 @@ class RailsFCGIHandler
175
208
  @gc_request_countdown = gc_request_period
176
209
  GC.enable; GC.start; GC.disable
177
210
  end
178
-
211
+
179
212
  def gc_countdown
180
213
  if gc_request_period
214
+ @gc_request_countdown ||= gc_request_period
181
215
  @gc_request_countdown -= 1
182
216
  run_gc! if @gc_request_countdown <= 0
183
217
  end
184
218
  end
185
-
219
+
186
220
  def close_connection(cgi)
187
- cgi.instance_variable_get("@request").finish
221
+ cgi.instance_variable_get("@request").finish if cgi
188
222
  end
189
- end
223
+ end