erails 2.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. data/CHANGELOG +3 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README +309 -0
  4. data/Rakefile +339 -0
  5. data/bin/about +4 -0
  6. data/bin/console +3 -0
  7. data/bin/dbconsole +3 -0
  8. data/bin/destroy +3 -0
  9. data/bin/erails +19 -0
  10. data/bin/generate +3 -0
  11. data/bin/performance/benchmarker +3 -0
  12. data/bin/performance/profiler +3 -0
  13. data/bin/performance/request +3 -0
  14. data/bin/plugin +3 -0
  15. data/bin/process/inspector +3 -0
  16. data/bin/process/reaper +3 -0
  17. data/bin/process/spawner +3 -0
  18. data/bin/runner +3 -0
  19. data/bin/server +3 -0
  20. data/builtin/rails_info/rails/info.rb +125 -0
  21. data/builtin/rails_info/rails/info_controller.rb +9 -0
  22. data/builtin/rails_info/rails/info_helper.rb +2 -0
  23. data/builtin/rails_info/rails_info_controller.rb +2 -0
  24. data/configs/apache.conf +40 -0
  25. data/configs/databases/frontbase.yml +28 -0
  26. data/configs/databases/mysql.yml +54 -0
  27. data/configs/databases/oracle.yml +39 -0
  28. data/configs/databases/postgresql.yml +48 -0
  29. data/configs/databases/sqlite2.yml +16 -0
  30. data/configs/databases/sqlite3.yml +19 -0
  31. data/configs/empty.log +0 -0
  32. data/configs/initializers/inflections.rb +10 -0
  33. data/configs/initializers/mime_types.rb +5 -0
  34. data/configs/initializers/new_rails_defaults.rb +17 -0
  35. data/configs/lighttpd.conf +54 -0
  36. data/configs/routes.rb +43 -0
  37. data/dispatches/dispatch.fcgi +24 -0
  38. data/dispatches/dispatch.rb +10 -0
  39. data/dispatches/gateway.cgi +97 -0
  40. data/doc/README_FOR_APP +2 -0
  41. data/environments/boot.rb +109 -0
  42. data/environments/development.rb +16 -0
  43. data/environments/environment.rb +71 -0
  44. data/environments/production.rb +22 -0
  45. data/environments/test.rb +22 -0
  46. data/fresh_rakefile +10 -0
  47. data/helpers/application.rb +15 -0
  48. data/helpers/application_helper.rb +3 -0
  49. data/helpers/test_helper.rb +38 -0
  50. data/html/404.html +30 -0
  51. data/html/422.html +30 -0
  52. data/html/500.html +30 -0
  53. data/html/favicon.ico +0 -0
  54. data/html/images/rails.png +0 -0
  55. data/html/index.html +274 -0
  56. data/html/javascripts/application.js +2 -0
  57. data/html/robots.txt +5 -0
  58. data/lib/code_statistics.rb +107 -0
  59. data/lib/commands/about.rb +3 -0
  60. data/lib/commands/console.rb +32 -0
  61. data/lib/commands/dbconsole.rb +67 -0
  62. data/lib/commands/destroy.rb +6 -0
  63. data/lib/commands/generate.rb +6 -0
  64. data/lib/commands/ncgi/listener +86 -0
  65. data/lib/commands/ncgi/tracker +69 -0
  66. data/lib/commands/performance/benchmarker.rb +24 -0
  67. data/lib/commands/performance/profiler.rb +50 -0
  68. data/lib/commands/performance/request.rb +6 -0
  69. data/lib/commands/plugin.rb +950 -0
  70. data/lib/commands/process/inspector.rb +68 -0
  71. data/lib/commands/process/reaper.rb +149 -0
  72. data/lib/commands/process/spawner.rb +219 -0
  73. data/lib/commands/process/spinner.rb +57 -0
  74. data/lib/commands/runner.rb +48 -0
  75. data/lib/commands/server.rb +39 -0
  76. data/lib/commands/servers/base.rb +31 -0
  77. data/lib/commands/servers/lighttpd.rb +94 -0
  78. data/lib/commands/servers/mongrel.rb +69 -0
  79. data/lib/commands/servers/new_mongrel.rb +16 -0
  80. data/lib/commands/servers/webrick.rb +66 -0
  81. data/lib/commands/update.rb +4 -0
  82. data/lib/commands.rb +17 -0
  83. data/lib/console_app.rb +30 -0
  84. data/lib/console_sandbox.rb +6 -0
  85. data/lib/console_with_helpers.rb +26 -0
  86. data/lib/dispatcher.rb +24 -0
  87. data/lib/fcgi_handler.rb +239 -0
  88. data/lib/initializer.rb +926 -0
  89. data/lib/rails/gem_builder.rb +21 -0
  90. data/lib/rails/gem_dependency.rb +129 -0
  91. data/lib/rails/mongrel_server/commands.rb +342 -0
  92. data/lib/rails/mongrel_server/handler.rb +55 -0
  93. data/lib/rails/plugin/loader.rb +152 -0
  94. data/lib/rails/plugin/locator.rb +100 -0
  95. data/lib/rails/plugin.rb +116 -0
  96. data/lib/rails/version.rb +9 -0
  97. data/lib/rails_generator/base.rb +263 -0
  98. data/lib/rails_generator/commands.rb +622 -0
  99. data/lib/rails_generator/generated_attribute.rb +42 -0
  100. data/lib/rails_generator/generators/applications/app/USAGE +9 -0
  101. data/lib/rails_generator/generators/applications/app/app_generator.rb +174 -0
  102. data/lib/rails_generator/generators/components/controller/USAGE +29 -0
  103. data/lib/rails_generator/generators/components/controller/controller_generator.rb +37 -0
  104. data/lib/rails_generator/generators/components/controller/templates/controller.rb +7 -0
  105. data/lib/rails_generator/generators/components/controller/templates/functional_test.rb +8 -0
  106. data/lib/rails_generator/generators/components/controller/templates/helper.rb +2 -0
  107. data/lib/rails_generator/generators/components/controller/templates/view.html.erb +2 -0
  108. data/lib/rails_generator/generators/components/integration_test/USAGE +8 -0
  109. data/lib/rails_generator/generators/components/integration_test/integration_test_generator.rb +16 -0
  110. data/lib/rails_generator/generators/components/integration_test/templates/integration_test.rb +10 -0
  111. data/lib/rails_generator/generators/components/mailer/USAGE +16 -0
  112. data/lib/rails_generator/generators/components/mailer/mailer_generator.rb +30 -0
  113. data/lib/rails_generator/generators/components/mailer/templates/fixture.erb +3 -0
  114. data/lib/rails_generator/generators/components/mailer/templates/fixture.rhtml +0 -0
  115. data/lib/rails_generator/generators/components/mailer/templates/mailer.rb +15 -0
  116. data/lib/rails_generator/generators/components/mailer/templates/unit_test.rb +21 -0
  117. data/lib/rails_generator/generators/components/mailer/templates/view.erb +3 -0
  118. data/lib/rails_generator/generators/components/mailer/templates/view.rhtml +0 -0
  119. data/lib/rails_generator/generators/components/migration/USAGE +29 -0
  120. data/lib/rails_generator/generators/components/migration/migration_generator.rb +20 -0
  121. data/lib/rails_generator/generators/components/migration/templates/migration.rb +11 -0
  122. data/lib/rails_generator/generators/components/model/USAGE +27 -0
  123. data/lib/rails_generator/generators/components/model/model_generator.rb +45 -0
  124. data/lib/rails_generator/generators/components/model/templates/fixtures.yml +19 -0
  125. data/lib/rails_generator/generators/components/model/templates/migration.rb +16 -0
  126. data/lib/rails_generator/generators/components/model/templates/model.rb +2 -0
  127. data/lib/rails_generator/generators/components/model/templates/unit_test.rb +8 -0
  128. data/lib/rails_generator/generators/components/observer/USAGE +13 -0
  129. data/lib/rails_generator/generators/components/observer/observer_generator.rb +16 -0
  130. data/lib/rails_generator/generators/components/observer/templates/observer.rb +2 -0
  131. data/lib/rails_generator/generators/components/observer/templates/unit_test.rb +8 -0
  132. data/lib/rails_generator/generators/components/plugin/USAGE +25 -0
  133. data/lib/rails_generator/generators/components/plugin/plugin_generator.rb +39 -0
  134. data/lib/rails_generator/generators/components/plugin/templates/MIT-LICENSE +20 -0
  135. data/lib/rails_generator/generators/components/plugin/templates/README +13 -0
  136. data/lib/rails_generator/generators/components/plugin/templates/Rakefile +22 -0
  137. data/lib/rails_generator/generators/components/plugin/templates/USAGE +8 -0
  138. data/lib/rails_generator/generators/components/plugin/templates/generator.rb +8 -0
  139. data/lib/rails_generator/generators/components/plugin/templates/init.rb +1 -0
  140. data/lib/rails_generator/generators/components/plugin/templates/install.rb +1 -0
  141. data/lib/rails_generator/generators/components/plugin/templates/plugin.rb +1 -0
  142. data/lib/rails_generator/generators/components/plugin/templates/tasks.rake +4 -0
  143. data/lib/rails_generator/generators/components/plugin/templates/uninstall.rb +1 -0
  144. data/lib/rails_generator/generators/components/plugin/templates/unit_test.rb +8 -0
  145. data/lib/rails_generator/generators/components/resource/USAGE +23 -0
  146. data/lib/rails_generator/generators/components/resource/resource_generator.rb +74 -0
  147. data/lib/rails_generator/generators/components/resource/templates/controller.rb +2 -0
  148. data/lib/rails_generator/generators/components/resource/templates/functional_test.rb +8 -0
  149. data/lib/rails_generator/generators/components/resource/templates/helper.rb +2 -0
  150. data/lib/rails_generator/generators/components/scaffold/USAGE +25 -0
  151. data/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb +93 -0
  152. data/lib/rails_generator/generators/components/scaffold/templates/controller.rb +85 -0
  153. data/lib/rails_generator/generators/components/scaffold/templates/functional_test.rb +45 -0
  154. data/lib/rails_generator/generators/components/scaffold/templates/helper.rb +2 -0
  155. data/lib/rails_generator/generators/components/scaffold/templates/layout.html.erb +17 -0
  156. data/lib/rails_generator/generators/components/scaffold/templates/style.css +54 -0
  157. data/lib/rails_generator/generators/components/scaffold/templates/view_edit.html.erb +18 -0
  158. data/lib/rails_generator/generators/components/scaffold/templates/view_index.html.erb +24 -0
  159. data/lib/rails_generator/generators/components/scaffold/templates/view_new.html.erb +17 -0
  160. data/lib/rails_generator/generators/components/scaffold/templates/view_show.html.erb +10 -0
  161. data/lib/rails_generator/generators/components/session_migration/USAGE +10 -0
  162. data/lib/rails_generator/generators/components/session_migration/session_migration_generator.rb +18 -0
  163. data/lib/rails_generator/generators/components/session_migration/templates/migration.rb +16 -0
  164. data/lib/rails_generator/lookup.rb +249 -0
  165. data/lib/rails_generator/manifest.rb +53 -0
  166. data/lib/rails_generator/options.rb +150 -0
  167. data/lib/rails_generator/scripts/destroy.rb +30 -0
  168. data/lib/rails_generator/scripts/generate.rb +7 -0
  169. data/lib/rails_generator/scripts/update.rb +12 -0
  170. data/lib/rails_generator/scripts.rb +89 -0
  171. data/lib/rails_generator/secret_key_generator.rb +164 -0
  172. data/lib/rails_generator/simple_logger.rb +46 -0
  173. data/lib/rails_generator/spec.rb +44 -0
  174. data/lib/rails_generator.rb +43 -0
  175. data/lib/railties_path.rb +1 -0
  176. data/lib/ruby_version_check.rb +17 -0
  177. data/lib/rubyprof_ext.rb +35 -0
  178. data/lib/source_annotation_extractor.rb +102 -0
  179. data/lib/tasks/annotations.rake +23 -0
  180. data/lib/tasks/databases.rake +389 -0
  181. data/lib/tasks/documentation.rake +80 -0
  182. data/lib/tasks/framework.rake +105 -0
  183. data/lib/tasks/gems.rake +64 -0
  184. data/lib/tasks/log.rake +9 -0
  185. data/lib/tasks/misc.rake +57 -0
  186. data/lib/tasks/rails.rb +8 -0
  187. data/lib/tasks/routes.rake +17 -0
  188. data/lib/tasks/statistics.rake +18 -0
  189. data/lib/tasks/testing.rake +118 -0
  190. data/lib/tasks/tmp.rake +37 -0
  191. data/lib/test_help.rb +28 -0
  192. data/lib/webrick_server.rb +165 -0
  193. metadata +356 -0
@@ -0,0 +1,94 @@
1
+ require 'rbconfig'
2
+ require 'commands/servers/base'
3
+
4
+ unless RUBY_PLATFORM !~ /mswin/ && !silence_stderr { `lighttpd -version` }.blank?
5
+ puts "PROBLEM: Lighttpd is not available on your system (or not in your path)"
6
+ exit 1
7
+ end
8
+
9
+ unless defined?(FCGI)
10
+ puts "PROBLEM: Lighttpd requires that the FCGI Ruby bindings are installed on the system"
11
+ exit 1
12
+ end
13
+
14
+ require 'initializer'
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'
19
+
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
30
+
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
+
37
+ require 'fileutils'
38
+
39
+ source = File.expand_path(File.join(File.dirname(__FILE__),
40
+ "..", "..", "..", "configs", "lighttpd.conf"))
41
+ puts "=> #{config_file} not found, copying from #{source}"
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
59
+ end
60
+
61
+ config = IO.read(config_file)
62
+ default_port, default_ip = 3000, '0.0.0.0'
63
+ port = config.scan(/^\s*server.port\s*=\s*(\d+)/).first rescue default_port
64
+ ip = config.scan(/^\s*server.bind\s*=\s*"([^"]+)"/).first rescue default_ip
65
+ puts "=> Enhanced Rails #{Rails.version} application starting on http://#{ip || default_ip}:#{port || default_port}"
66
+
67
+ tail_thread = nil
68
+
69
+ if !detach
70
+ puts "=> Call with -d to detach"
71
+ puts "=> Ctrl-C to shutdown server (see config/lighttpd.conf for options)"
72
+ detach = false
73
+ tail_thread = tail(configuration.log_path)
74
+ end
75
+
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'
90
+ end
91
+
92
+ `rake tmp:sockets:clear` # Remove sockets on clean shutdown
93
+ end
94
+ end
@@ -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 "=> Enhanced Rails #{Rails.version} 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
+ puts "=> Call with -d to detach"
54
+ puts "=> Ctrl-C to shutdown server"
55
+
56
+ log = Pathname.new("#{File.expand_path(RAILS_ROOT)}/log/#{RAILS_ENV}.log").cleanpath
57
+ open(log, (File::WRONLY | File::APPEND | File::CREAT)) unless File.exist? log
58
+ tail_thread = tail(log)
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
@@ -0,0 +1,16 @@
1
+ unless defined?(Mongrel)
2
+ abort "PROBLEM: Mongrel is not available on your system (or not in your path)"
3
+ end
4
+
5
+ require 'rails/mongrel_server/commands'
6
+
7
+ GemPlugin::Manager.instance.load "rails::mongrel" => GemPlugin::INCLUDE, "rails" => GemPlugin::EXCLUDE
8
+
9
+ case ARGV[0] ||= 'start'
10
+ when 'start', 'stop', 'restart'
11
+ ARGV[0] = "rails::mongrelserver::#{ARGV[0]}"
12
+ end
13
+
14
+ if not Mongrel::Command::Registry.instance.run ARGV
15
+ exit 1
16
+ end
@@ -0,0 +1,66 @@
1
+ require 'webrick'
2
+ require 'optparse'
3
+ require 'commands/servers/base'
4
+
5
+ OPTIONS = {
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
+
15
+ }
16
+
17
+ ARGV.options do |opts|
18
+ script_name = File.basename($0)
19
+ opts.banner = "Usage: ruby #{script_name} [options]"
20
+
21
+ opts.separator ""
22
+
23
+ opts.on("-p", "--port=port", Integer,
24
+ "Runs Rails on the specified port.",
25
+ "Default: 3000") { |v| OPTIONS[:port] = v }
26
+ opts.on("-b", "--binding=ip", String,
27
+ "Binds Rails to the specified ip.",
28
+ "Default: 0.0.0.0") { |v| OPTIONS[:ip] = v }
29
+ opts.on("-e", "--environment=name", String,
30
+ "Specifies the environment to run this server under (test/development/production).",
31
+ "Default: development") { |v| OPTIONS[:environment] = v }
32
+ opts.on("-m", "--mime-types=filename", String,
33
+ "Specifies an Apache style mime.types configuration file to be used for mime types",
34
+ "Default: none") { |mime_types_file| OPTIONS[:mime_types] = WEBrick::HTTPUtils::load_mime_types(mime_types_file) }
35
+
36
+ opts.on("-d", "--daemon",
37
+ "Make Rails run as a Daemon (only works if fork is available -- meaning on *nix)."
38
+ ) { OPTIONS[:server_type] = WEBrick::Daemon }
39
+
40
+ opts.on("-u", "--debugger", "Enable ruby-debugging for the server.") { OPTIONS[:debugger] = true }
41
+
42
+ opts.on("-c", "--charset=charset", String,
43
+ "Set default charset for output.",
44
+ "Default: UTF-8") { |v| OPTIONS[:charset] = v }
45
+
46
+ opts.separator ""
47
+
48
+ opts.on("-h", "--help",
49
+ "Show this help message.") { puts opts; exit }
50
+
51
+ opts.parse!
52
+ end
53
+
54
+ start_debugger if OPTIONS[:debugger]
55
+
56
+ ENV["RAILS_ENV"] = OPTIONS[:environment]
57
+ RAILS_ENV.replace(OPTIONS[:environment]) if defined?(RAILS_ENV)
58
+
59
+ require RAILS_ROOT + "/config/environment"
60
+ require 'webrick_server'
61
+
62
+ OPTIONS['working_directory'] = File.expand_path(RAILS_ROOT)
63
+
64
+ puts "=> Rails #{Rails.version} application started on http://#{OPTIONS[:ip]}:#{OPTIONS[:port]}"
65
+ puts "=> Ctrl-C to shutdown server; call with --help for options" if OPTIONS[:server_type] == WEBrick::SimpleServer
66
+ DispatchServlet.dispatch(OPTIONS)
@@ -0,0 +1,4 @@
1
+ require "#{RAILS_ROOT}/config/environment"
2
+ require 'rails_generator'
3
+ require 'rails_generator/scripts/update'
4
+ Rails::Generator::Scripts::Update.new.run(ARGV)
data/lib/commands.rb ADDED
@@ -0,0 +1,17 @@
1
+ commands = Dir["#{File.dirname(__FILE__)}/commands/*.rb"].collect { |file_path| File.basename(file_path).split(".").first }
2
+
3
+ if commands.include?(ARGV.first)
4
+ require "#{File.dirname(__FILE__)}/commands/#{ARGV.shift}"
5
+ else
6
+ puts <<-USAGE
7
+ The 'run' provides a unified access point for all the default Rails' commands.
8
+
9
+ Usage: ./script/run <command> [OPTIONS]
10
+
11
+ Examples:
12
+ ./script/run generate controller Admin
13
+ ./script/run process reaper
14
+
15
+ USAGE
16
+ puts "Choose: #{commands.join(", ")}"
17
+ end
@@ -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
28
+ dispatcher.reload_application
29
+ true
30
+ end
@@ -0,0 +1,6 @@
1
+ ActiveRecord::Base.send :increment_open_transactions
2
+ ActiveRecord::Base.connection.begin_db_transaction
3
+ at_exit do
4
+ ActiveRecord::Base.connection.rollback_db_transaction
5
+ ActiveRecord::Base.send :decrement_open_transactions
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_dependency '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 ADDED
@@ -0,0 +1,24 @@
1
+ #--
2
+ # Copyright (c) 2004-2008 David Heinemeier Hansson
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+ require 'action_controller/dispatcher'
24
+ Dispatcher = ActionController::Dispatcher
@@ -0,0 +1,239 @@
1
+ require 'fcgi'
2
+ require 'logger'
3
+ require 'dispatcher'
4
+ require 'rbconfig'
5
+
6
+ class RailsFCGIHandler
7
+ SIGNALS = {
8
+ 'HUP' => :reload,
9
+ 'INT' => :exit_now,
10
+ 'TERM' => :exit_now,
11
+ 'USR1' => :exit,
12
+ 'USR2' => :restart
13
+ }
14
+ GLOBAL_SIGNALS = SIGNALS.keys - %w(USR1)
15
+
16
+ attr_reader :when_ready
17
+
18
+ attr_accessor :log_file_path
19
+ attr_accessor :gc_request_period
20
+
21
+
22
+ # Initialize and run the FastCGI instance, passing arguments through to new.
23
+ def self.process!(*args, &block)
24
+ new(*args, &block).process!
25
+ end
26
+
27
+ # Initialize the FastCGI instance with the path to a crash log
28
+ # detailing unhandled exceptions (default RAILS_ROOT/log/fastcgi.crash.log)
29
+ # and the number of requests to process between garbage collection runs
30
+ # (default nil for normal GC behavior.) Optionally, pass a block which
31
+ # takes this instance as an argument for further configuration.
32
+ def initialize(log_file_path = nil, gc_request_period = nil)
33
+ self.log_file_path = log_file_path || "#{RAILS_ROOT}/log/fastcgi.crash.log"
34
+ self.gc_request_period = gc_request_period
35
+
36
+ # Yield for additional configuration.
37
+ yield self if block_given?
38
+
39
+ # Safely install signal handlers.
40
+ install_signal_handlers
41
+
42
+ # Start error timestamp at 11 seconds ago.
43
+ @last_error_on = Time.now - 11
44
+ end
45
+
46
+ def process!(provider = FCGI)
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'
67
+ end
68
+ end
69
+ end
70
+
71
+
72
+ protected
73
+ def process_each_request(provider)
74
+ cgi = nil
75
+
76
+ catch :exit do
77
+ provider.each_cgi do |cgi|
78
+ process_request(cgi)
79
+
80
+ case when_ready
81
+ when :reload
82
+ reload!
83
+ when :restart
84
+ close_connection(cgi)
85
+ restart!
86
+ when :exit
87
+ close_connection(cgi)
88
+ throw :exit
89
+ end
90
+ end
91
+ end
92
+ rescue SignalException => signal
93
+ raise unless signal.message == 'SIGUSR1'
94
+ close_connection(cgi)
95
+ end
96
+
97
+ def process_request(cgi)
98
+ @processing, @when_ready = true, nil
99
+ gc_countdown
100
+
101
+ with_signal_handler 'USR1' do
102
+ begin
103
+ Dispatcher.dispatch(cgi)
104
+ rescue SignalException, SystemExit
105
+ raise
106
+ rescue Exception => error
107
+ dispatcher_error error, 'unhandled dispatch error'
108
+ end
109
+ end
110
+ ensure
111
+ @processing = false
112
+ end
113
+
114
+ def logger
115
+ @logger ||= Logger.new(@log_file_path)
116
+ end
117
+
118
+ def dispatcher_log(level, msg)
119
+ time_str = Time.now.strftime("%d/%b/%Y:%H:%M:%S")
120
+ logger.send(level, "[#{time_str} :: #{$$}] #{msg}")
121
+ rescue Exception => log_error # Logger errors
122
+ STDERR << "Couldn't write to #{@log_file_path.inspect}: #{msg}\n"
123
+ STDERR << " #{log_error.class}: #{log_error.message}\n"
124
+ end
125
+
126
+ def dispatcher_error(e, msg = "")
127
+ error_message =
128
+ "Dispatcher failed to catch: #{e} (#{e.class})\n" +
129
+ " #{e.backtrace.join("\n ")}\n#{msg}"
130
+ dispatcher_log(:error, error_message)
131
+ end
132
+
133
+ def install_signal_handlers
134
+ GLOBAL_SIGNALS.each { |signal| install_signal_handler(signal) }
135
+ end
136
+
137
+ def install_signal_handler(signal, handler = nil)
138
+ if SIGNALS.include?(signal) && self.class.method_defined?(name = "#{SIGNALS[signal]}_handler")
139
+ handler ||= method(name).to_proc
140
+
141
+ begin
142
+ trap(signal, handler)
143
+ rescue ArgumentError
144
+ dispatcher_log :warn, "Ignoring unsupported signal #{signal}."
145
+ end
146
+ else
147
+ dispatcher_log :warn, "Ignoring unsupported signal #{signal}."
148
+ end
149
+ end
150
+
151
+ def with_signal_handler(signal)
152
+ install_signal_handler(signal)
153
+ yield
154
+ ensure
155
+ install_signal_handler(signal, 'DEFAULT')
156
+ end
157
+
158
+ def exit_now_handler(signal)
159
+ dispatcher_log :info, "asked to stop immediately"
160
+ exit
161
+ end
162
+
163
+ def exit_handler(signal)
164
+ dispatcher_log :info, "asked to stop ASAP"
165
+ if @processing
166
+ @when_ready = :exit
167
+ else
168
+ throw :exit
169
+ end
170
+ end
171
+
172
+ def reload_handler(signal)
173
+ dispatcher_log :info, "asked to reload ASAP"
174
+ if @processing
175
+ @when_ready = :reload
176
+ else
177
+ reload!
178
+ end
179
+ end
180
+
181
+ def restart_handler(signal)
182
+ dispatcher_log :info, "asked to restart ASAP"
183
+ if @processing
184
+ @when_ready = :restart
185
+ else
186
+ restart!
187
+ end
188
+ end
189
+
190
+ def restart!
191
+ config = ::Config::CONFIG
192
+ ruby = File::join(config['bindir'], config['ruby_install_name']) + config['EXEEXT']
193
+ command_line = [ruby, $0, ARGV].flatten.join(' ')
194
+
195
+ dispatcher_log :info, "restarted"
196
+
197
+ # close resources as they won't be closed by
198
+ # the OS when using exec
199
+ logger.close rescue nil
200
+ RAILS_DEFAULT_LOGGER.close rescue nil
201
+
202
+ exec(command_line)
203
+ end
204
+
205
+ def reload!
206
+ run_gc! if gc_request_period
207
+ restore!
208
+ @when_ready = nil
209
+ dispatcher_log :info, "reloaded"
210
+ end
211
+
212
+ # Make a note of $" so we can safely reload this instance.
213
+ def mark_features!
214
+ @features = $".clone
215
+ end
216
+
217
+ def restore!
218
+ $".replace @features
219
+ Dispatcher.reset_application!
220
+ ActionController::Routing::Routes.reload
221
+ end
222
+
223
+ def run_gc!
224
+ @gc_request_countdown = gc_request_period
225
+ GC.enable; GC.start; GC.disable
226
+ end
227
+
228
+ def gc_countdown
229
+ if gc_request_period
230
+ @gc_request_countdown ||= gc_request_period
231
+ @gc_request_countdown -= 1
232
+ run_gc! if @gc_request_countdown <= 0
233
+ end
234
+ end
235
+
236
+ def close_connection(cgi)
237
+ cgi.instance_variable_get("@request").finish if cgi
238
+ end
239
+ end