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
@@ -0,0 +1,6 @@
1
+ require "#{RAILS_ROOT}/config/environment"
2
+ require 'rails_generator'
3
+ require 'rails_generator/scripts/generate'
4
+
5
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
6
+ Rails::Generator::Scripts::Generate.new.run(ARGV)
File without changes
File without changes
@@ -0,0 +1,26 @@
1
+ #!/usr/local/bin/ruby
2
+
3
+ if ARGV.empty?
4
+ puts "Usage: ./script/perform benchmarker [times] 'Person.expensive_way' 'Person.another_expensive_way' ..."
5
+ exit 1
6
+ end
7
+
8
+ begin
9
+ N = Integer(ARGV.first)
10
+ ARGV.shift
11
+ rescue ArgumentError
12
+ N = 1
13
+ end
14
+
15
+ require RAILS_ROOT + '/config/environment'
16
+ require 'benchmark'
17
+ include Benchmark
18
+
19
+ # Don't include compilation in the benchmark
20
+ ARGV.each { |expression| eval(expression) }
21
+
22
+ bm(6) do |x|
23
+ ARGV.each_with_index do |expression, idx|
24
+ x.report("##{idx + 1}") { N.times { eval(expression) } }
25
+ end
26
+ end
@@ -1,12 +1,12 @@
1
1
  #!/usr/local/bin/ruby
2
2
  if ARGV.empty?
3
- $stderr.puts "Usage: profiler 'Person.expensive_method(10)' [times]"
3
+ $stderr.puts "Usage: ./script/perform profiler 'Person.expensive_method(10)' [times]"
4
4
  exit(1)
5
5
  end
6
6
 
7
7
  # Keep the expensive require out of the profile.
8
8
  $stderr.puts 'Loading Rails...'
9
- require File.dirname(__FILE__) + '/../config/environment'
9
+ require RAILS_ROOT + '/config/environment'
10
10
 
11
11
  # Define a method to profile.
12
12
  if ARGV[1] and ARGV[1].to_i > 1
@@ -26,6 +26,7 @@ begin
26
26
  require 'rubyprof_ext'
27
27
  Prof.print_profile(results, $stderr)
28
28
  rescue LoadError
29
+ require 'profiler'
29
30
  $stderr.puts 'Using the standard Ruby profiler.'
30
31
  Profiler__.start_profile
31
32
  profile_me
@@ -0,0 +1,130 @@
1
+ require 'optparse'
2
+ require 'net/http'
3
+ require 'uri'
4
+
5
+ if RUBY_PLATFORM =~ /mswin32/ then abort("Reaper is only for Unix") end
6
+
7
+ # Instances of this class represent a single running process. Processes may
8
+ # be queried by "keyword" to find those that meet a specific set of criteria.
9
+ class ProgramProcess
10
+ class << self
11
+
12
+ # Searches for all processes matching the given keywords, and then invokes
13
+ # a specific action on each of them. This is useful for (e.g.) reloading a
14
+ # set of processes:
15
+ #
16
+ # ProgramProcess.process_keywords(:reload, "basecamp")
17
+ def process_keywords(action, *keywords)
18
+ processes = keywords.collect { |keyword| find_by_keyword(keyword) }.flatten
19
+
20
+ if processes.empty?
21
+ puts "Couldn't find any process matching: #{keywords.join(" or ")}"
22
+ else
23
+ processes.each do |process|
24
+ puts "#{action.capitalize}ing #{process}"
25
+ process.send(action)
26
+ end
27
+ end
28
+ end
29
+
30
+ # Searches for all processes matching the given keyword:
31
+ #
32
+ # ProgramProcess.find_by_keyword("basecamp")
33
+ def find_by_keyword(keyword)
34
+ process_lines_with_keyword(keyword).split("\n").collect { |line|
35
+ next if line.include?("inq") || line.include?("ps -ax") || line.include?("grep")
36
+ pid, *command = line.split
37
+ new(pid, command.join(" "))
38
+ }.compact
39
+ end
40
+
41
+ private
42
+ def process_lines_with_keyword(keyword)
43
+ `ps -ax -o 'pid command' | grep #{keyword}`
44
+ end
45
+ end
46
+
47
+ # Create a new ProgramProcess instance that represents the process with the
48
+ # given pid, running the given command.
49
+ def initialize(pid, command)
50
+ @pid, @command = pid, command
51
+ end
52
+
53
+ # Forces the (rails) application to reload by sending a +HUP+ signal to the
54
+ # process.
55
+ def reload
56
+ `kill -s HUP #{@pid}`
57
+ end
58
+
59
+ # Forces the (rails) application to gracefully terminate by sending a
60
+ # +TERM+ signal to the process.
61
+ def graceful
62
+ `kill -s TERM #{@pid}`
63
+ end
64
+
65
+ # Forces the (rails) application to terminate immediately by sending a -9
66
+ # signal to the process.
67
+ def kill
68
+ `kill -9 #{@pid}`
69
+ end
70
+
71
+ # Send a +USR1+ signal to the process.
72
+ def usr1
73
+ `kill -s USR1 #{@pid}`
74
+ end
75
+
76
+ # Force the (rails) application to restart by sending a +USR2+ signal to the
77
+ # process.
78
+ def restart
79
+ `kill -s USR2 #{@pid}`
80
+ end
81
+
82
+ def to_s #:nodoc:
83
+ "[#{@pid}] #{@command}"
84
+ end
85
+ end
86
+
87
+ OPTIONS = {
88
+ :action => "restart",
89
+ :dispatcher => File.expand_path(RAILS_ROOT + '/public/dispatch.fcgi')
90
+ }
91
+
92
+ ARGV.options do |opts|
93
+ opts.banner = "Usage: reaper [options]"
94
+
95
+ opts.separator ""
96
+
97
+ opts.on <<-EOF
98
+ Description:
99
+ The reaper is used to restart, reload, gracefully exit, and forcefully exit FCGI processes
100
+ running a Rails Dispatcher. This is commonly done when a new version of the application
101
+ is available, so the existing processes can be updated to use the latest code.
102
+
103
+ The reaper actions are:
104
+
105
+ * restart : Restarts the application by reloading both application and framework code
106
+ * reload : Only reloads the application, but not the framework (like the development environment)
107
+ * graceful: Marks all of the processes for exit after the next request
108
+ * kill : Forcefully exists all processes regardless of whether they're currently serving a request
109
+
110
+ Restart is the most common and default action.
111
+
112
+ Examples:
113
+ reaper # restarts the default dispatcher
114
+ reaper -a reload
115
+ reaper -a exit -d /my/special/dispatcher.fcgi
116
+ EOF
117
+
118
+ opts.on(" Options:")
119
+
120
+ opts.on("-a", "--action=name", "reload|graceful|kill (default: #{OPTIONS[:action]})", String) { |OPTIONS[:action]| }
121
+ opts.on("-d", "--dispatcher=path", "default: #{OPTIONS[:dispatcher]}", String) { |OPTIONS[:dispatcher]| }
122
+
123
+ opts.separator ""
124
+
125
+ opts.on("-h", "--help", "Show this help message.") { puts opts; exit }
126
+
127
+ opts.parse!
128
+ end
129
+
130
+ ProgramProcess.process_keywords(OPTIONS[:action], OPTIONS[:dispatcher])
@@ -0,0 +1,52 @@
1
+ require 'optparse'
2
+
3
+ def spawn(port)
4
+ print "Starting FCGI on port: #{port}\n "
5
+ system("#{OPTIONS[:spawner]} -f #{OPTIONS[:dispatcher]} -p #{port}")
6
+ end
7
+
8
+ OPTIONS = {
9
+ :environment => "production",
10
+ :spawner => '/usr/bin/env spawn-fcgi',
11
+ :dispatcher => File.expand_path(RAILS_ROOT + '/public/dispatch.fcgi'),
12
+ :port => 8000,
13
+ :instances => 3
14
+ }
15
+
16
+ ARGV.options do |opts|
17
+ opts.banner = "Usage: spawner [options]"
18
+
19
+ opts.separator ""
20
+
21
+ opts.on <<-EOF
22
+ Description:
23
+ The spawner is a wrapper for spawn-fcgi that makes it easier to start multiple FCGI
24
+ processes running the Rails dispatcher. The spawn-fcgi command is included with the lighttpd
25
+ web server, but can be used with both Apache and lighttpd (and any other web server supporting
26
+ externally managed FCGI processes).
27
+
28
+ You decide a starting port (default is 8000) and the number of FCGI process instances you'd
29
+ like to run. So if you pick 9100 and 3 instances, you'll start processes on 9100, 9101, and 9102.
30
+
31
+ Examples:
32
+ spawner # starts instances on 8000, 8001, and 8002
33
+ spawner -p 9100 -i 10 # starts 10 instances counting from 9100 to 9109
34
+ EOF
35
+
36
+ opts.on(" Options:")
37
+
38
+ opts.on("-p", "--port=number", Integer, "Starting port number (default: #{OPTIONS[:port]})") { |OPTIONS[:port]| }
39
+ opts.on("-i", "--instances=number", Integer, "Number of instances (default: #{OPTIONS[:instances]})") { |OPTIONS[:instances]| }
40
+ opts.on("-e", "--environment=name", String, "test|development|production (default: #{OPTIONS[:environment]})") { |OPTIONS[:environment]| }
41
+ opts.on("-s", "--spawner=path", String, "default: #{OPTIONS[:spawner]}") { |OPTIONS[:spawner]| }
42
+ opts.on("-d", "--dispatcher=path", String, "default: #{OPTIONS[:dispatcher]}") { |dispatcher| OPTIONS[:dispatcher] = File.expand_path(dispatcher) }
43
+
44
+ opts.separator ""
45
+
46
+ opts.on("-h", "--help", "Show this help message.") { puts opts; exit }
47
+
48
+ opts.parse!
49
+ end
50
+
51
+ ENV["RAILS_ENV"] = OPTIONS[:environment]
52
+ OPTIONS[:instances].times { |i| spawn(OPTIONS[:port] + i) }
@@ -0,0 +1,57 @@
1
+ require 'optparse'
2
+
3
+ def daemonize #:nodoc:
4
+ exit if fork # Parent exits, child continues.
5
+ Process.setsid # Become session leader.
6
+ exit if fork # Zap session leader. See [1].
7
+ Dir.chdir "/" # Release old working directory.
8
+ File.umask 0000 # Ensure sensible umask. Adjust as needed.
9
+ STDIN.reopen "/dev/null" # Free file descriptors and
10
+ STDOUT.reopen "/dev/null", "a" # point them somewhere sensible.
11
+ STDERR.reopen STDOUT # STDOUT/ERR should better go to a logfile.
12
+ end
13
+
14
+ OPTIONS = {
15
+ :interval => 5.0,
16
+ :command => File.expand_path(RAILS_ROOT + '/script/process/spawner'),
17
+ :daemon => false
18
+ }
19
+
20
+ ARGV.options do |opts|
21
+ opts.banner = "Usage: spinner [options]"
22
+
23
+ opts.separator ""
24
+
25
+ opts.on <<-EOF
26
+ Description:
27
+ The spinner is a protection loop for the spawner, which will attempt to restart any FCGI processes
28
+ that might have been exited or outright crashed. It's a brute-force attempt that'll just try
29
+ to run the spawner every X number of seconds, so it does pose a light load on the server.
30
+
31
+ Examples:
32
+ spinner # attempts to run the spawner with default settings every second with output on the terminal
33
+ spinner -i 3 -d # only run the spawner every 3 seconds and detach from the terminal to become a daemon
34
+ spinner -c '/path/to/app/script/process/spawner -p 9000 -i 10' -d # using custom spawner
35
+ EOF
36
+
37
+ opts.on(" Options:")
38
+
39
+ opts.on("-c", "--command=path", String) { |OPTIONS[:command]| }
40
+ opts.on("-i", "--interval=seconds", Float) { |OPTIONS[:interval]| }
41
+ opts.on("-d", "--daemon") { |OPTIONS[:daemon]| }
42
+
43
+ opts.separator ""
44
+
45
+ opts.on("-h", "--help", "Show this help message.") { puts opts; exit }
46
+
47
+ opts.parse!
48
+ end
49
+
50
+ daemonize if OPTIONS[:daemon]
51
+
52
+ trap(OPTIONS[:daemon] ? "TERM" : "INT") { exit }
53
+
54
+ loop do
55
+ system(OPTIONS[:command])
56
+ sleep(OPTIONS[:interval])
57
+ end
@@ -0,0 +1,27 @@
1
+ require 'optparse'
2
+
3
+ options = { :environment => (ENV['RAILS_ENV'] || "development").dup }
4
+
5
+ ARGV.options do |opts|
6
+ script_name = File.basename($0)
7
+ opts.banner = "Usage: runner 'puts Person.find(1).name' [options]"
8
+
9
+ opts.separator ""
10
+
11
+ opts.on("-e", "--environment=name", String,
12
+ "Specifies the environment for the runner to operate under (test/development/production).",
13
+ "Default: development") { |options[:environment]| }
14
+
15
+ opts.separator ""
16
+
17
+ opts.on("-h", "--help",
18
+ "Show this help message.") { puts opts; exit }
19
+
20
+ opts.parse!
21
+ end
22
+
23
+ ENV["RAILS_ENV"] = options[:environment]
24
+ RAILS_ENV.replace(options[:environment]) if defined?(RAILS_ENV)
25
+
26
+ require RAILS_ROOT + '/config/environment'
27
+ eval(ARGV.first)
@@ -0,0 +1,59 @@
1
+ require 'webrick'
2
+ require 'optparse'
3
+
4
+ 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
12
+ }
13
+
14
+ ARGV.options do |opts|
15
+ script_name = File.basename($0)
16
+ opts.banner = "Usage: ruby #{script_name} [options]"
17
+
18
+ opts.separator ""
19
+
20
+ opts.on("-p", "--port=port", Integer,
21
+ "Runs Rails on the specified port.",
22
+ "Default: 3000") { |OPTIONS[:port]| }
23
+ opts.on("-b", "--binding=ip", String,
24
+ "Binds Rails to the specified ip.",
25
+ "Default: 0.0.0.0") { |OPTIONS[:ip]| }
26
+ opts.on("-e", "--environment=name", String,
27
+ "Specifies the environment to run this server under (test/development/production).",
28
+ "Default: development") { |OPTIONS[:environment]| }
29
+ opts.on("-m", "--mime-types=filename", String,
30
+ "Specifies an Apache style mime.types configuration file to be used for mime types",
31
+ "Default: none") { |mime_types_file| OPTIONS[:mime_types] = WEBrick::HTTPUtils::load_mime_types(mime_types_file) }
32
+
33
+ opts.on("-d", "--daemon",
34
+ "Make Rails run as a Daemon (only works if fork is available -- meaning on *nix)."
35
+ ) { OPTIONS[:server_type] = WEBrick::Daemon }
36
+
37
+ opts.on("-c", "--charset=charset", String,
38
+ "Set default charset for output.",
39
+ "Default: UTF-8") { |OPTIONS[:charset]| }
40
+
41
+ opts.separator ""
42
+
43
+ opts.on("-h", "--help",
44
+ "Show this help message.") { puts opts; exit }
45
+
46
+ opts.parse!
47
+ end
48
+
49
+ ENV["RAILS_ENV"] = OPTIONS[:environment]
50
+ RAILS_ENV.replace(OPTIONS[:environment]) if defined?(RAILS_ENV)
51
+
52
+ require RAILS_ROOT + "/config/environment"
53
+ require 'webrick_server'
54
+
55
+ OPTIONS['working_directory'] = File.expand_path(RAILS_ROOT)
56
+
57
+ puts "=> Rails application started on http://#{OPTIONS[:ip]}:#{OPTIONS[:port]}"
58
+ puts "=> Ctrl-C to shutdown server; call with --help for options" if OPTIONS[:server_type] == WEBrick::SimpleServer
59
+ DispatchServlet.dispatch(OPTIONS)
@@ -1,5 +1,4 @@
1
- #!/usr/local/bin/ruby
2
- require File.dirname(__FILE__) + '/../config/environment'
1
+ require "#{RAILS_ROOT}/config/environment"
3
2
  require 'rails_generator'
4
3
  require 'rails_generator/scripts/update'
5
4
  Rails::Generator::Scripts::Update.new.run(ARGV)
@@ -21,10 +21,14 @@
21
21
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
22
  #++
23
23
 
24
- require 'breakpoint'
25
-
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.
26
27
  class Dispatcher
27
28
  class << self
29
+
30
+ # Dispatch the given CGI request, using the given session options, and
31
+ # emitting the output via the given output.
28
32
  def dispatch(cgi = CGI.new, session_options = ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS, output = $stdout)
29
33
  begin
30
34
  request, response = ActionController::CgiRequest.new(cgi, session_options), ActionController::CgiResponse.new(cgi)
@@ -37,9 +41,13 @@ class Dispatcher
37
41
  end
38
42
  end
39
43
 
44
+ # Reset the application by clearing out loaded controllers, views, actions,
45
+ # mailers, and so forth. This allows them to be loaded again without having
46
+ # to restart the server (WEBrick, FastCGI, etc.).
40
47
  def reset_application!
41
48
  Controllers.clear!
42
49
  Dependencies.clear
50
+ ActiveRecord::Base.reset_subclasses
43
51
  Dependencies.remove_subclasses_for(ActiveRecord::Base, ActiveRecord::Observer, ActionController::Base)
44
52
  Dependencies.remove_subclasses_for(ActionMailer::Base) if defined?(ActionMailer::Base)
45
53
  end
@@ -47,7 +55,7 @@ class Dispatcher
47
55
  private
48
56
  def prepare_application
49
57
  ActionController::Routing::Routes.reload if Dependencies.load?
50
- Breakpoint.activate_drb("druby://localhost:#{BREAKPOINT_SERVER_PORT}", nil, !defined?(FastCGI)) if defined?(BREAKPOINT_SERVER_PORT) rescue nil
58
+ prepare_breakpoint
51
59
  Controllers.const_load!(:ApplicationController, "application") unless Controllers.const_defined?(:ApplicationController)
52
60
  end
53
61
 
@@ -55,5 +63,14 @@ class Dispatcher
55
63
  reset_application! if Dependencies.load?
56
64
  Breakpoint.deactivate_drb if defined?(BREAKPOINT_SERVER_PORT)
57
65
  end
66
+
67
+ def prepare_breakpoint
68
+ return unless defined?(BREAKPOINT_SERVER_PORT)
69
+ require 'breakpoint'
70
+ Breakpoint.activate_drb("druby://localhost:#{BREAKPOINT_SERVER_PORT}", nil, !defined?(FastCGI))
71
+ true
72
+ rescue
73
+ nil
74
+ end
58
75
  end
59
76
  end