rails 0.8.5 → 0.9.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.
- data/CHANGELOG +86 -0
- data/README +48 -8
- data/Rakefile +87 -108
- data/bin/breakpointer +3 -0
- data/bin/breakpointer_for_gem +4 -0
- data/bin/console +30 -0
- data/bin/generate +41 -0
- data/bin/rails +1 -1
- data/{dispatches/dispatch.servlet → bin/server} +15 -11
- data/configs/apache.conf +12 -27
- data/configs/database.yml +9 -2
- data/dispatches/dispatch.fcgi +2 -2
- data/dispatches/dispatch.rb +2 -2
- data/doc/index.html +12 -36
- data/environments/development.rb +5 -0
- data/environments/production.rb +3 -6
- data/environments/shared.rb +46 -20
- data/environments/shared_for_gem.rb +41 -8
- data/environments/test.rb +3 -6
- data/fresh_rakefile +25 -21
- data/generators/controller/USAGE +28 -0
- data/generators/controller/controller_generator.rb +22 -0
- data/generators/controller/templates/controller.rb +10 -0
- data/generators/{templates/controller_test.erb → controller/templates/functional_test.rb} +1 -1
- data/generators/{templates/helper.erb → controller/templates/helper.rb} +0 -0
- data/generators/controller/templates/view.rhtml +2 -0
- data/generators/mailer/USAGE +27 -0
- data/generators/mailer/mailer_generator.rb +22 -0
- data/generators/{templates/mailer_action.rhtml → mailer/templates/fixture.rhtml} +0 -0
- data/generators/{templates/mailer.erb → mailer/templates/mailer.rb} +4 -4
- data/generators/{templates/mailer_test.erb → mailer/templates/unit_test.rb} +2 -10
- data/generators/mailer/templates/view.rhtml +3 -0
- data/generators/model/USAGE +17 -0
- data/generators/model/model_generator.rb +10 -0
- data/generators/model/templates/fixtures.yml +1 -0
- data/generators/{templates/model.erb → model/templates/model.rb} +0 -2
- data/generators/{templates/model_test.erb → model/templates/unit_test.rb} +2 -3
- data/generators/scaffold/USAGE +25 -0
- data/generators/scaffold/scaffold_generator.rb +53 -0
- data/generators/scaffold/templates/controller.rb +57 -0
- data/generators/scaffold/templates/fixtures.yml +7 -0
- data/generators/scaffold/templates/functional_test.rb +79 -0
- data/generators/scaffold/templates/layout.rhtml +11 -0
- data/generators/scaffold/templates/style.css +53 -0
- data/generators/scaffold/templates/view_edit.rhtml +7 -0
- data/generators/scaffold/templates/view_list.rhtml +24 -0
- data/generators/scaffold/templates/view_new.rhtml +6 -0
- data/generators/scaffold/templates/view_show.rhtml +8 -0
- data/helpers/{abstract_application.rb → application.rb} +1 -4
- data/helpers/test_helper.rb +4 -5
- data/lib/binding_of_caller.rb +81 -0
- data/lib/breakpoint.rb +526 -0
- data/lib/breakpoint_client.rb +167 -0
- data/lib/dispatcher.rb +43 -12
- data/lib/rails_generator.rb +175 -0
- data/lib/webrick_server.rb +48 -52
- metadata +49 -21
- data/gem_snapshot +0 -14
- data/generators/new_controller.rb +0 -43
- data/generators/new_crud.rb +0 -34
- data/generators/new_mailer.rb +0 -43
- data/generators/new_model.rb +0 -31
- data/generators/templates/controller.erb +0 -24
- data/generators/templates/controller_view.rhtml +0 -10
- data/generators/templates/mailer_fixture.rhtml +0 -4
- data/lib/generator.rb +0 -112
@@ -0,0 +1,167 @@
|
|
1
|
+
require 'breakpoint'
|
2
|
+
require 'optparse'
|
3
|
+
require 'timeout'
|
4
|
+
|
5
|
+
options = {
|
6
|
+
:ClientURI => nil,
|
7
|
+
:ServerURI => "druby://localhost:42531",
|
8
|
+
:RetryDelay => 1,
|
9
|
+
:Verbose => false
|
10
|
+
}
|
11
|
+
|
12
|
+
ARGV.options do |opts|
|
13
|
+
script_name = File.basename($0)
|
14
|
+
opts.banner = [
|
15
|
+
"Usage: ruby #{script_name} [options] [server uri]",
|
16
|
+
"",
|
17
|
+
"This tool lets you connect to a breakpoint service ",
|
18
|
+
"which was started via Breakpoint.activate_drb.",
|
19
|
+
"",
|
20
|
+
"The server uri defaults to druby://localhost:42531"
|
21
|
+
].join("\n")
|
22
|
+
|
23
|
+
opts.separator ""
|
24
|
+
|
25
|
+
opts.on("-c", "--client-uri=uri",
|
26
|
+
"Run the client on the specified uri.",
|
27
|
+
"This can be used to specify the port",
|
28
|
+
"that the client uses to allow for back",
|
29
|
+
"connections from the server.",
|
30
|
+
"Default: Find a good URI automatically.",
|
31
|
+
"Example: -c druby://localhost:12345"
|
32
|
+
) { |options[:ClientURI]| }
|
33
|
+
|
34
|
+
opts.on("-s", "--server-uri=uri",
|
35
|
+
"Connect to the server specified at the",
|
36
|
+
"specified uri.",
|
37
|
+
"Default: druby://localhost:42531"
|
38
|
+
) { |options[:ServerURI]| }
|
39
|
+
|
40
|
+
opts.on("-v", "--verbose",
|
41
|
+
"Report all connections and disconnections",
|
42
|
+
"Default: false"
|
43
|
+
) { |options[:Verbose]| }
|
44
|
+
|
45
|
+
opts.on("-R", "--retry-delay=delay", Integer,
|
46
|
+
"Automatically try to reconnect to the",
|
47
|
+
"server after delay seconds when the",
|
48
|
+
"connection failed or timed out.",
|
49
|
+
"A value of 0 disables automatical",
|
50
|
+
"reconnecting completely.",
|
51
|
+
"Default: 10"
|
52
|
+
) { |options[:RetryDelay]| }
|
53
|
+
|
54
|
+
opts.separator ""
|
55
|
+
|
56
|
+
opts.on("-h", "--help",
|
57
|
+
"Show this help message."
|
58
|
+
) { puts opts; exit }
|
59
|
+
|
60
|
+
opts.parse!
|
61
|
+
end
|
62
|
+
|
63
|
+
options[:ServerURI] = ARGV[0] if ARGV[0]
|
64
|
+
|
65
|
+
puts "Waiting for initial breakpoint..."
|
66
|
+
|
67
|
+
loop do
|
68
|
+
DRb.start_service(options[:ClientURI])
|
69
|
+
|
70
|
+
begin
|
71
|
+
service = DRbObject.new(nil, options[:ServerURI])
|
72
|
+
|
73
|
+
begin
|
74
|
+
timeout(10) { service.ping }
|
75
|
+
rescue Timeout::Error, DRb::DRbConnError
|
76
|
+
if options[:Verbose]
|
77
|
+
puts "",
|
78
|
+
" *** Breakpoint service didn't respond to ping request ***",
|
79
|
+
" This likely happened because of a misconfigured ACL (see the",
|
80
|
+
" documentation of Breakpoint.activate_drb, note that by default",
|
81
|
+
" you can only connect to a remote Breakpoint service via a SSH",
|
82
|
+
" tunnel), but might also be caused by an extremely slow connection.",
|
83
|
+
""
|
84
|
+
end
|
85
|
+
raise
|
86
|
+
end
|
87
|
+
|
88
|
+
begin
|
89
|
+
service.register_eval_handler do |code|
|
90
|
+
result = eval(code, TOPLEVEL_BINDING)
|
91
|
+
if result
|
92
|
+
DRbObject.new(result)
|
93
|
+
else
|
94
|
+
result
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
service.register_collision_handler do
|
99
|
+
msg = [
|
100
|
+
" *** Breakpoint service collision ***",
|
101
|
+
" Another Breakpoint service tried to use the",
|
102
|
+
" port already occupied by this one. It will",
|
103
|
+
" keep waiting until this Breakpoint service",
|
104
|
+
" is shut down.",
|
105
|
+
" ",
|
106
|
+
" If you are using the Breakpoint library for",
|
107
|
+
" debugging a Rails or other CGI application",
|
108
|
+
" this likely means that this Breakpoint",
|
109
|
+
" session belongs to an earlier, outdated",
|
110
|
+
" request and should be shut down via 'exit'."
|
111
|
+
].join("\n")
|
112
|
+
|
113
|
+
if RUBY_PLATFORM["win"] then
|
114
|
+
# This sucks. Sorry, I'm not doing this because
|
115
|
+
# I like funky message boxes -- I need to do this
|
116
|
+
# because on Windows I have no way of displaying
|
117
|
+
# my notification via puts() when gets() is still
|
118
|
+
# being performed on STDIN. I have not found a
|
119
|
+
# better solution.
|
120
|
+
begin
|
121
|
+
require 'tk'
|
122
|
+
root = TkRoot.new { withdraw }
|
123
|
+
Tk.messageBox('message' => msg, 'type' => 'ok')
|
124
|
+
root.destroy
|
125
|
+
rescue Exception
|
126
|
+
puts "", msg, ""
|
127
|
+
end
|
128
|
+
else
|
129
|
+
puts "", msg, ""
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
service.register_handler do |workspace, message|
|
134
|
+
puts message
|
135
|
+
IRB.start(nil, nil, workspace)
|
136
|
+
puts "", "Resumed execution. Waiting for next breakpoint...", ""
|
137
|
+
end
|
138
|
+
|
139
|
+
puts "Connection established. Waiting for breakpoint...", "" if options[:Verbose]
|
140
|
+
|
141
|
+
loop do
|
142
|
+
begin
|
143
|
+
service.ping
|
144
|
+
rescue DRb::DRbConnError => error
|
145
|
+
puts "Server exited. Closing connection..." if options[:Verbose]
|
146
|
+
break
|
147
|
+
end
|
148
|
+
|
149
|
+
sleep(0.5)
|
150
|
+
end
|
151
|
+
ensure
|
152
|
+
service.unregister_handler
|
153
|
+
end
|
154
|
+
rescue Exception => error
|
155
|
+
if options[:RetryDelay] > 0 then
|
156
|
+
puts "No connection to breakpoint service at #{options[:ServerURI]}:", " (#{error.inspect})" if options[:Verbose]
|
157
|
+
error.backtrace if $DEBUG
|
158
|
+
|
159
|
+
puts " Reconnecting in #{options[:RetryDelay]} seconds..." if options[:Verbose]
|
160
|
+
|
161
|
+
sleep options[:RetryDelay]
|
162
|
+
retry
|
163
|
+
else
|
164
|
+
raise
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
data/lib/dispatcher.rb
CHANGED
@@ -21,26 +21,57 @@
|
|
21
21
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
22
|
#++
|
23
23
|
|
24
|
+
require 'breakpoint'
|
25
|
+
|
24
26
|
class Dispatcher
|
25
|
-
|
27
|
+
def self.dispatch(cgi = CGI.new, session_options = ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS)
|
28
|
+
Breakpoint.activate_drb("druby://localhost:#{BREAKPOINT_SERVER_PORT}", nil, !defined?(FastCGI)) if defined?(BREAKPOINT_SERVER_PORT)
|
26
29
|
|
27
|
-
def self.dispatch(cgi = CGI.new, session_options = DEFAULT_SESSION_OPTIONS, error_page = nil)
|
28
30
|
begin
|
29
31
|
request = ActionController::CgiRequest.new(cgi, session_options)
|
30
32
|
response = ActionController::CgiResponse.new(cgi)
|
33
|
+
|
34
|
+
controller_name, module_name = controller_name(request.parameters), module_name(request.parameters)
|
31
35
|
|
32
|
-
|
36
|
+
require_dependency("application")
|
37
|
+
require_dependency(controller_path(controller_name, module_name))
|
33
38
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
39
|
+
controller_class(controller_name).process(request, response).out
|
40
|
+
rescue Object => exception
|
41
|
+
ActionController::Base.process_with_exception(request, response, exception).out
|
42
|
+
ensure
|
43
|
+
if ActionController::Base.reload_dependencies
|
44
|
+
Object.send(:remove_const, "ApplicationController") if Object.const_defined?(:ApplicationController)
|
45
|
+
Object.send(:remove_const, controller_class_name(controller_name)) if Object.const_defined?(controller_class_name(controller_name))
|
46
|
+
ActiveRecord::Base.reset_associations_loaded
|
47
|
+
ActiveRecord::Base.reset_column_information_and_inheritable_attributes_for_all_subclasses
|
41
48
|
end
|
42
49
|
|
43
|
-
if
|
50
|
+
Breakpoint.deactivate_drb if defined?(BREAKPOINT_SERVER_PORT)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.controller_path(controller_name, module_name = nil)
|
55
|
+
if module_name
|
56
|
+
"#{module_name}/#{Inflector.underscore(controller_name)}_controller"
|
57
|
+
else
|
58
|
+
"#{Inflector.underscore(controller_name)}_controller"
|
44
59
|
end
|
45
60
|
end
|
46
|
-
|
61
|
+
|
62
|
+
def self.controller_class(controller_name)
|
63
|
+
Object.const_get(controller_class_name(controller_name))
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.controller_class_name(controller_name)
|
67
|
+
"#{Inflector.camelize(controller_name)}Controller"
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.controller_name(parameters)
|
71
|
+
parameters["controller"].gsub(/[^_a-zA-Z0-9]/, "").untaint
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.module_name(parameters)
|
75
|
+
parameters["module"].gsub(/[^_a-zA-Z0-9]/, "").untaint if parameters["module"]
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Rails
|
4
|
+
module Generator
|
5
|
+
class GeneratorError < StandardError; end
|
6
|
+
class UsageError < GeneratorError; end
|
7
|
+
|
8
|
+
CONTRIB_ROOT = "#{RAILS_ROOT}/script/generators"
|
9
|
+
BUILTIN_ROOT = "#{File.dirname(__FILE__)}/../generators"
|
10
|
+
DEFAULT_SEARCH_PATHS = [CONTRIB_ROOT, BUILTIN_ROOT]
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def instance(name, args = [], search_paths = DEFAULT_SEARCH_PATHS)
|
14
|
+
# RAILS_ROOT constant must be set.
|
15
|
+
unless Object.const_get(:RAILS_ROOT)
|
16
|
+
raise GeneratorError, "RAILS_ROOT must be set. Did you require 'config/environment'?"
|
17
|
+
end
|
18
|
+
|
19
|
+
# Force canonical name.
|
20
|
+
name = Inflector.underscore(name.downcase)
|
21
|
+
|
22
|
+
# Search for filesystem path to requested generator.
|
23
|
+
unless path = find_generator_path(name, search_paths)
|
24
|
+
raise GeneratorError, "#{name} generator not found."
|
25
|
+
end
|
26
|
+
|
27
|
+
# Check for templates directory.
|
28
|
+
template_root = "#{path}/templates"
|
29
|
+
unless File.directory?(template_root)
|
30
|
+
raise GeneratorError, "missing template directory #{template_root}"
|
31
|
+
end
|
32
|
+
|
33
|
+
# Require class file according to naming convention.
|
34
|
+
require "#{path}/#{name}_generator.rb"
|
35
|
+
|
36
|
+
# Find class according to naming convention. Allow Nesting::In::Modules.
|
37
|
+
class_name = Inflector.classify("#{name}_generator")
|
38
|
+
unless klass = find_generator_class(name)
|
39
|
+
raise GeneratorError, "no #{class_name} class defined in #{path}/#{name}_generator.rb"
|
40
|
+
end
|
41
|
+
|
42
|
+
# Instantiate and return generator.
|
43
|
+
klass.new(template_root, RAILS_ROOT, search_paths, args)
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
def builtin_generators
|
48
|
+
generators([BUILTIN_ROOT])
|
49
|
+
end
|
50
|
+
|
51
|
+
def contrib_generators
|
52
|
+
generators([CONTRIB_ROOT])
|
53
|
+
end
|
54
|
+
|
55
|
+
def generators(search_paths)
|
56
|
+
generator_paths(search_paths).keys.uniq.sort
|
57
|
+
end
|
58
|
+
|
59
|
+
# Find all generator paths.
|
60
|
+
def generator_paths(search_paths)
|
61
|
+
@paths ||= {}
|
62
|
+
unless @paths[search_paths]
|
63
|
+
paths = Hash.new { |h,k| h[k] = [] }
|
64
|
+
search_paths.each do |path|
|
65
|
+
Dir["#{path}/[a-z]*"].each do |dir|
|
66
|
+
paths[File.basename(dir)] << dir if File.directory?(dir)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
@paths[search_paths] = paths
|
70
|
+
end
|
71
|
+
@paths[search_paths]
|
72
|
+
end
|
73
|
+
|
74
|
+
def find_generator_path(name, search_paths)
|
75
|
+
generator_paths(search_paths)[name].first
|
76
|
+
end
|
77
|
+
|
78
|
+
# Find all generator classes.
|
79
|
+
def generator_classes
|
80
|
+
classes = Hash.new { |h,k| h[k] = [] }
|
81
|
+
class_re = /([^:]+)Generator$/
|
82
|
+
ObjectSpace.each_object(Class) do |object|
|
83
|
+
if md = class_re.match(object.name) and object < Rails::Generator::Base
|
84
|
+
classes[Inflector.underscore(md.captures.first)] << object
|
85
|
+
end
|
86
|
+
end
|
87
|
+
classes
|
88
|
+
end
|
89
|
+
|
90
|
+
def find_generator_class(name)
|
91
|
+
generator_classes[name].first
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
# Talk about generators.
|
97
|
+
class Base
|
98
|
+
attr_reader :template_root, :destination_root, :args, :options,
|
99
|
+
:class_name, :singular_name, :plural_name
|
100
|
+
|
101
|
+
alias_method :file_name, :singular_name
|
102
|
+
alias_method :table_name, :plural_name
|
103
|
+
|
104
|
+
def self.generator_name
|
105
|
+
Inflector.underscore(name.gsub('Generator', ''))
|
106
|
+
end
|
107
|
+
|
108
|
+
def initialize(template_root, destination_root, search_paths, args)
|
109
|
+
@template_root, @destination_root = template_root, destination_root
|
110
|
+
usage if args.empty?
|
111
|
+
@search_paths, @original_args = search_paths, args.dup
|
112
|
+
@class_name, @singular_name, @plural_name = inflect_names(args.shift)
|
113
|
+
@options = extract_options!(args)
|
114
|
+
@args = args
|
115
|
+
end
|
116
|
+
|
117
|
+
protected
|
118
|
+
# Look up another generator with the same arguments.
|
119
|
+
def generator(name)
|
120
|
+
Rails::Generator.instance(name, @original_args, @search_paths)
|
121
|
+
end
|
122
|
+
|
123
|
+
# Generate a file for a Rails application using an ERuby template.
|
124
|
+
# Looks up and evalutes a template by name and writes the result
|
125
|
+
# to a file relative to +destination_root+. The template
|
126
|
+
# is evaluated in the context of the optional eval_binding argument.
|
127
|
+
#
|
128
|
+
# The ERB template uses explicit trim mode to best control the
|
129
|
+
# proliferation of whitespace in generated code. <%- trims leading
|
130
|
+
# whitespace; -%> trims trailing whitespace including one newline.
|
131
|
+
def template(template_name, destination_path, eval_binding = nil)
|
132
|
+
# Determine full paths for source and destination files.
|
133
|
+
template_path = find_template_path(template_name)
|
134
|
+
destination_path = File.join(destination_root, destination_path)
|
135
|
+
|
136
|
+
# Create destination directories.
|
137
|
+
FileUtils.mkdir_p(File.dirname(destination_path))
|
138
|
+
|
139
|
+
# Render template and write result.
|
140
|
+
eval_binding ||= binding
|
141
|
+
contents = ERB.new(File.read(template_path), nil, '-').result(eval_binding)
|
142
|
+
File.open(destination_path, 'w') { |file| file.write(contents) }
|
143
|
+
end
|
144
|
+
|
145
|
+
def usage
|
146
|
+
raise UsageError.new, File.read(usage_path)
|
147
|
+
end
|
148
|
+
|
149
|
+
private
|
150
|
+
def find_template_path(template_name)
|
151
|
+
name, path = template_name.split('/', 2)
|
152
|
+
if path.nil?
|
153
|
+
File.join(template_root, name)
|
154
|
+
elsif generator_path = Rails::Generator.find_generator_path(name, @search_paths)
|
155
|
+
File.join(generator_path, 'templates', path)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def inflect_names(name)
|
160
|
+
camel = Inflector.camelize(Inflector.underscore(name))
|
161
|
+
under = Inflector.underscore(camel)
|
162
|
+
plural = Inflector.pluralize(under)
|
163
|
+
[camel, under, plural]
|
164
|
+
end
|
165
|
+
|
166
|
+
def extract_options!(args)
|
167
|
+
if args.last.is_a?(Hash) then args.pop else {} end
|
168
|
+
end
|
169
|
+
|
170
|
+
def usage_path
|
171
|
+
"#{template_root}/../USAGE"
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
data/lib/webrick_server.rb
CHANGED
@@ -7,6 +7,8 @@ require 'stringio'
|
|
7
7
|
include WEBrick
|
8
8
|
|
9
9
|
class DispatchServlet < WEBrick::HTTPServlet::AbstractServlet
|
10
|
+
REQUEST_MUTEX = Mutex.new
|
11
|
+
|
10
12
|
def self.dispatch(options = {})
|
11
13
|
Socket.do_not_reverse_lookup = true # patch for OS X
|
12
14
|
|
@@ -24,14 +26,19 @@ class DispatchServlet < WEBrick::HTTPServlet::AbstractServlet
|
|
24
26
|
end
|
25
27
|
|
26
28
|
def do_GET(req, res)
|
27
|
-
|
28
|
-
unless
|
29
|
-
unless
|
30
|
-
unless
|
31
|
-
|
29
|
+
begin
|
30
|
+
unless handle_index(req, res)
|
31
|
+
unless handle_dispatch(req, res)
|
32
|
+
unless handle_file(req, res)
|
33
|
+
REQUEST_MUTEX.lock
|
34
|
+
unless handle_mapped(req, res)
|
35
|
+
raise WEBrick::HTTPStatus::NotFound, "`#{req.path}' not found."
|
36
|
+
end
|
32
37
|
end
|
33
38
|
end
|
34
39
|
end
|
40
|
+
ensure
|
41
|
+
REQUEST_MUTEX.unlock if REQUEST_MUTEX.locked?
|
35
42
|
end
|
36
43
|
end
|
37
44
|
|
@@ -42,7 +49,7 @@ class DispatchServlet < WEBrick::HTTPServlet::AbstractServlet
|
|
42
49
|
if @server_options[:index_controller]
|
43
50
|
res.set_redirect WEBrick::HTTPStatus::MovedPermanently, "/#{@server_options[:index_controller]}/"
|
44
51
|
else
|
45
|
-
res.set_redirect WEBrick::HTTPStatus::MovedPermanently, "/_doc/
|
52
|
+
res.set_redirect WEBrick::HTTPStatus::MovedPermanently, "/_doc/"
|
46
53
|
end
|
47
54
|
|
48
55
|
return true
|
@@ -59,15 +66,13 @@ class DispatchServlet < WEBrick::HTTPServlet::AbstractServlet
|
|
59
66
|
res.set_error(err)
|
60
67
|
return true
|
61
68
|
rescue => err
|
62
|
-
p err
|
63
69
|
return false
|
64
70
|
end
|
65
71
|
end
|
66
72
|
|
67
73
|
def handle_mapped(req, res)
|
68
|
-
|
69
|
-
|
70
|
-
query = "controller=#{controller}&action=#{action}&id=#{id}"
|
74
|
+
if mappings = DispatchServlet.parse_uri(req.request_uri.path)
|
75
|
+
query = mappings.collect { |pair| "#{pair.first}=#{pair.last}" }.join("&")
|
71
76
|
query << "&#{req.request_uri.query}" if req.request_uri.query
|
72
77
|
origin = req.request_uri.path + "?" + query
|
73
78
|
req.request_uri.path = "/dispatch.rb"
|
@@ -86,43 +91,19 @@ class DispatchServlet < WEBrick::HTTPServlet::AbstractServlet
|
|
86
91
|
env["REQUEST_URI"] = origin if origin
|
87
92
|
|
88
93
|
data = nil
|
89
|
-
|
90
|
-
|
91
|
-
$stdin, $stdout = StringIO.new(req.body || ""), StringIO.new
|
94
|
+
$old_stdin, $old_stdout = $stdin, $stdout
|
95
|
+
$stdin, $stdout = StringIO.new(req.body || ""), StringIO.new
|
92
96
|
|
93
|
-
|
94
|
-
|
95
|
-
|
97
|
+
begin
|
98
|
+
require 'cgi'
|
99
|
+
CGI.send(:define_method, :env_table) { env }
|
96
100
|
|
97
|
-
|
101
|
+
load File.join(@server_options[:server_root], "dispatch.rb")
|
98
102
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
end
|
104
|
-
else
|
105
|
-
begin
|
106
|
-
require 'rbconfig'
|
107
|
-
ruby_interpreter = Config::CONFIG['ruby_install_name'] || 'ruby'
|
108
|
-
rescue Object
|
109
|
-
ruby_interpreter = 'ruby'
|
110
|
-
end
|
111
|
-
|
112
|
-
dispatch_rb_path = File.expand_path(File.join(@server_options[:server_root], "dispatch.rb"))
|
113
|
-
IO.popen(ruby_interpreter, "rb+") do |ruby|
|
114
|
-
ruby.puts <<-END
|
115
|
-
require 'cgi'
|
116
|
-
require 'stringio'
|
117
|
-
env = #{env.inspect}
|
118
|
-
CGI.send(:define_method, :env_table) { env }
|
119
|
-
$stdin = StringIO.new(#{(req.body || "").inspect})
|
120
|
-
|
121
|
-
eval "load '#{dispatch_rb_path}'", binding, #{dispatch_rb_path.inspect}
|
122
|
-
END
|
123
|
-
ruby.close_write
|
124
|
-
data = ruby.read
|
125
|
-
end
|
103
|
+
$stdout.rewind
|
104
|
+
data = $stdout.read
|
105
|
+
ensure
|
106
|
+
$stdin, $stdout = $old_stdin, $old_stdout
|
126
107
|
end
|
127
108
|
|
128
109
|
raw_header, body = *data.split(/^[\xd\xa]+/on, 2)
|
@@ -141,18 +122,33 @@ class DispatchServlet < WEBrick::HTTPServlet::AbstractServlet
|
|
141
122
|
end
|
142
123
|
|
143
124
|
def self.parse_uri(path)
|
144
|
-
component = /([-_a-zA-Z0-9]+)/
|
125
|
+
component, id = /([-_a-zA-Z0-9]+)/, /([0-9]+)/
|
145
126
|
|
146
127
|
case path.sub(%r{^/(?:fcgi|mruby|cgi)/}, "/")
|
147
128
|
when %r{^/#{component}/?$} then
|
148
|
-
|
149
|
-
when %r{^/#{component}/#{component}
|
150
|
-
|
151
|
-
when %r{^/#{component}/#{component}/#{
|
152
|
-
|
129
|
+
{ :controller => $1, :action => "index" }
|
130
|
+
when %r{^/#{component}/#{component}$} then
|
131
|
+
{ :controller => $1, :action => $2 }
|
132
|
+
when %r{^/#{component}/#{component}/#{id}$} then
|
133
|
+
{ :controller => $1, :action => $2, :id => $3 }
|
134
|
+
|
135
|
+
when %r{^/#{component}/#{component}/$} then
|
136
|
+
{ :module => $1, :controller => $2, :action => "index" }
|
137
|
+
when %r{^/#{component}/#{component}/#{component}$} then
|
138
|
+
if DispatchServlet.modules(component).include?($1)
|
139
|
+
{ :module => $1, :controller => $2, :action => $3 }
|
140
|
+
else
|
141
|
+
{ :controller => $1, :action => $2, :id => $3 }
|
142
|
+
end
|
143
|
+
when %r{^/#{component}/#{component}/#{component}/#{id}$} then
|
144
|
+
{ :module => $1, :controller => $2, :action => $3, :id => $4 }
|
153
145
|
else
|
154
|
-
|
146
|
+
false
|
155
147
|
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def self.modules(module_pattern = '[^.]+')
|
151
|
+
path = RAILS_ROOT + '/app/controllers'
|
152
|
+
Dir.entries(path).grep(/^#{module_pattern}$/).find_all {|e| File.directory?("#{path}/#{e}")}
|
156
153
|
end
|
157
|
-
|
158
154
|
end
|