merb-core 0.9.3 → 0.9.4
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +1 -1
- data/README +3 -3
- data/Rakefile +144 -33
- data/bin/merb +0 -0
- data/bin/merb-specs +0 -0
- data/docs/bootloading.dox +1 -0
- data/docs/merb-core-call-stack-diagram.mmap +0 -0
- data/docs/merb-core-call-stack-diagram.pdf +0 -0
- data/docs/merb-core-call-stack-diagram.png +0 -0
- data/lib/merb-core.rb +159 -37
- data/lib/merb-core/autoload.rb +1 -0
- data/lib/merb-core/bootloader.rb +208 -92
- data/lib/merb-core/config.rb +20 -6
- data/lib/merb-core/controller/abstract_controller.rb +113 -61
- data/lib/merb-core/controller/exceptions.rb +28 -13
- data/lib/merb-core/controller/merb_controller.rb +73 -44
- data/lib/merb-core/controller/mime.rb +25 -7
- data/lib/merb-core/controller/mixins/authentication.rb +1 -1
- data/lib/merb-core/controller/mixins/controller.rb +44 -8
- data/lib/merb-core/controller/mixins/render.rb +191 -128
- data/lib/merb-core/controller/mixins/responder.rb +65 -63
- data/lib/merb-core/controller/template.rb +103 -54
- data/lib/merb-core/core_ext.rb +7 -12
- data/lib/merb-core/core_ext/kernel.rb +128 -136
- data/lib/merb-core/dispatch/cookies.rb +26 -4
- data/lib/merb-core/dispatch/default_exception/default_exception.rb +93 -0
- data/lib/merb-core/dispatch/default_exception/views/_css.html.erb +198 -0
- data/lib/merb-core/dispatch/default_exception/views/_javascript.html.erb +73 -0
- data/lib/merb-core/dispatch/default_exception/views/index.html.erb +92 -0
- data/lib/merb-core/dispatch/dispatcher.rb +156 -224
- data/lib/merb-core/dispatch/request.rb +126 -25
- data/lib/merb-core/dispatch/router.rb +61 -6
- data/lib/merb-core/dispatch/router/behavior.rb +122 -41
- data/lib/merb-core/dispatch/router/route.rb +147 -22
- data/lib/merb-core/dispatch/session.rb +52 -2
- data/lib/merb-core/dispatch/session/cookie.rb +4 -2
- data/lib/merb-core/dispatch/session/memcached.rb +38 -27
- data/lib/merb-core/dispatch/session/memory.rb +18 -11
- data/lib/merb-core/dispatch/worker.rb +28 -0
- data/lib/merb-core/gem_ext/erubis.rb +58 -0
- data/lib/merb-core/logger.rb +3 -31
- data/lib/merb-core/plugins.rb +25 -3
- data/lib/merb-core/rack.rb +18 -12
- data/lib/merb-core/rack/adapter.rb +10 -8
- data/lib/merb-core/rack/adapter/ebb.rb +2 -2
- data/lib/merb-core/rack/adapter/irb.rb +31 -21
- data/lib/merb-core/rack/adapter/swiftiplied_mongrel.rb +26 -0
- data/lib/merb-core/rack/adapter/thin.rb +19 -9
- data/lib/merb-core/rack/adapter/thin_turbo.rb +24 -0
- data/lib/merb-core/rack/application.rb +9 -84
- data/lib/merb-core/rack/middleware.rb +26 -0
- data/lib/merb-core/rack/middleware/path_prefix.rb +31 -0
- data/lib/merb-core/rack/middleware/profiler.rb +19 -0
- data/lib/merb-core/rack/middleware/static.rb +45 -0
- data/lib/merb-core/server.rb +27 -9
- data/lib/merb-core/tasks/audit.rake +68 -0
- data/lib/merb-core/tasks/merb.rb +1 -0
- data/lib/merb-core/tasks/merb_rake_helper.rb +12 -0
- data/lib/merb-core/tasks/stats.rake +71 -0
- data/lib/merb-core/test.rb +2 -1
- data/lib/merb-core/test/helpers/multipart_request_helper.rb +3 -3
- data/lib/merb-core/test/helpers/request_helper.rb +66 -24
- data/lib/merb-core/test/matchers/controller_matchers.rb +36 -4
- data/lib/merb-core/test/matchers/route_matchers.rb +12 -3
- data/lib/merb-core/test/matchers/view_matchers.rb +3 -3
- data/lib/merb-core/test/run_specs.rb +1 -0
- data/lib/merb-core/test/tasks/spectasks.rb +13 -5
- data/lib/merb-core/test/test_ext/string.rb +14 -0
- data/lib/merb-core/vendor/facets/dictionary.rb +3 -3
- data/lib/merb-core/vendor/facets/inflect.rb +82 -37
- data/lib/merb-core/version.rb +2 -2
- data/spec/private/config/config_spec.rb +39 -4
- data/spec/private/core_ext/kernel_spec.rb +3 -14
- data/spec/private/dispatch/bootloader_spec.rb +1 -1
- data/spec/private/dispatch/cookies_spec.rb +181 -69
- data/spec/private/dispatch/fixture/app/controllers/exceptions.rb +0 -2
- data/spec/private/dispatch/fixture/app/controllers/foo.rb +0 -2
- data/spec/private/dispatch/fixture/config/rack.rb +10 -0
- data/spec/private/dispatch/fixture/log/merb_test.log +7054 -1802
- data/spec/private/dispatch/route_params_spec.rb +2 -3
- data/spec/private/dispatch/session_mixin_spec.rb +47 -0
- data/spec/private/plugins/plugin_spec.rb +73 -59
- data/spec/private/router/behavior_spec.rb +60 -0
- data/spec/private/router/fixture/log/merb_test.log +1693 -0
- data/spec/private/router/route_spec.rb +414 -0
- data/spec/private/router/router_spec.rb +175 -0
- data/spec/private/vendor/facets/plural_spec.rb +564 -0
- data/spec/private/vendor/facets/singular_spec.rb +489 -0
- data/spec/public/abstract_controller/controllers/cousins.rb +41 -0
- data/spec/public/abstract_controller/controllers/helpers.rb +12 -2
- data/spec/public/abstract_controller/controllers/partial.rb +17 -2
- data/spec/public/abstract_controller/controllers/render.rb +16 -1
- data/spec/public/abstract_controller/controllers/views/helpers/capture_eq/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/helpers/capture_with_args/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_two_throw_contents/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections_and_counter/_collection.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections_and_counter/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/with_absolute_partial/_partial.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/with_absolute_partial/index.erb +1 -0
- data/spec/public/abstract_controller/filter_spec.rb +20 -1
- data/spec/public/abstract_controller/helper_spec.rb +10 -2
- data/spec/public/abstract_controller/partial_spec.rb +8 -0
- data/spec/public/abstract_controller/render_spec.rb +8 -0
- data/spec/public/abstract_controller/spec_helper.rb +7 -3
- data/spec/public/boot_loader/boot_loader_spec.rb +2 -2
- data/spec/public/controller/base_spec.rb +10 -2
- data/spec/public/controller/config/init.rb +6 -0
- data/spec/public/controller/controllers/authentication.rb +9 -11
- data/spec/public/controller/controllers/base.rb +2 -8
- data/spec/public/controller/controllers/cookies.rb +16 -0
- data/spec/public/controller/controllers/dispatcher.rb +35 -0
- data/spec/public/controller/controllers/display.rb +62 -14
- data/spec/public/controller/controllers/redirect.rb +36 -0
- data/spec/public/controller/controllers/responder.rb +37 -11
- data/spec/public/controller/controllers/views/layout/custom_arg.json.erb +1 -0
- data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/class_and_local_provides/index.html.erb +1 -0
- data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/class_and_local_provides/index.xml.erb +1 -0
- data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/display_with_template/no_layout.html.erb +1 -0
- data/spec/public/controller/cookies_spec.rb +23 -0
- data/spec/public/controller/dispatcher_spec.rb +411 -0
- data/spec/public/controller/display_spec.rb +43 -10
- data/spec/public/controller/redirect_spec.rb +33 -0
- data/spec/public/controller/responder_spec.rb +79 -11
- data/spec/public/controller/spec_helper.rb +3 -1
- data/spec/public/controller/url_spec.rb +10 -0
- data/spec/public/core/merb_core_spec.rb +11 -0
- data/spec/public/core_ext/fixtures/core_ext_dependency.rb +2 -0
- data/spec/public/core_ext/kernel_spec.rb +9 -0
- data/spec/public/core_ext/spec_helper.rb +1 -0
- data/spec/public/directory_structure/directory/log/merb_test.log +3729 -272
- data/spec/public/directory_structure/directory_spec.rb +3 -4
- data/spec/public/logger/logger_spec.rb +4 -4
- data/spec/public/reloading/directory/log/merb_test.log +288066 -15
- data/spec/public/reloading/reload_spec.rb +49 -27
- data/spec/public/request/multipart_spec.rb +26 -0
- data/spec/public/request/request_spec.rb +21 -2
- data/spec/public/router/fixation_spec.rb +27 -0
- data/spec/public/router/fixture/log/merb_test.log +30050 -0
- data/spec/public/router/nested_matches_spec.rb +97 -0
- data/spec/public/router/resource_spec.rb +1 -9
- data/spec/public/router/resources_spec.rb +0 -20
- data/spec/public/router/spec_helper.rb +27 -9
- data/spec/public/router/special_spec.rb +21 -8
- data/spec/public/template/template_spec.rb +17 -5
- data/spec/public/test/controller_matchers_spec.rb +10 -0
- data/spec/public/test/request_helper_spec.rb +29 -0
- data/spec/public/test/route_helper_spec.rb +18 -1
- data/spec/public/test/route_matchers_spec.rb +28 -1
- data/spec/public/test/view_matchers_spec.rb +3 -3
- data/spec/spec_helper.rb +56 -12
- metadata +89 -47
- data/lib/merb-core/core_ext/class.rb +0 -299
- data/lib/merb-core/core_ext/hash.rb +0 -426
- data/lib/merb-core/core_ext/mash.rb +0 -154
- data/lib/merb-core/core_ext/object.rb +0 -147
- data/lib/merb-core/core_ext/object_space.rb +0 -14
- data/lib/merb-core/core_ext/rubygems.rb +0 -28
- data/lib/merb-core/core_ext/set.rb +0 -46
- data/lib/merb-core/core_ext/string.rb +0 -89
- data/lib/merb-core/core_ext/time.rb +0 -13
- data/lib/merb-core/dispatch/exceptions.html.erb +0 -297
- data/spec/private/core_ext/class_spec.rb +0 -22
- data/spec/private/core_ext/hash_spec.rb +0 -522
- data/spec/private/core_ext/object_spec.rb +0 -121
- data/spec/private/core_ext/set_spec.rb +0 -26
- data/spec/private/core_ext/string_spec.rb +0 -167
- data/spec/private/core_ext/time_spec.rb +0 -16
- data/spec/private/dispatch/dispatch_spec.rb +0 -26
- data/spec/private/dispatch/fixture/log/development.log +0 -1
- data/spec/private/dispatch/fixture/log/merb.4000.pid +0 -1
- data/spec/private/dispatch/fixture/log/production.log +0 -1
- data/spec/private/dispatch/fixture/merb.4000.pid +0 -1
- data/spec/private/rack/application_spec.rb +0 -43
- data/spec/public/controller/log/merb.4000.pid +0 -1
- data/spec/public/directory_structure/directory/log/merb.4000.pid +0 -1
- data/spec/public/directory_structure/directory/merb.4000.pid +0 -1
- data/spec/public/reloading/directory/log/merb.4000.pid +0 -1
- data/spec/public/reloading/directory/merb.4000.pid +0 -1
@@ -0,0 +1,31 @@
|
|
1
|
+
module Merb
|
2
|
+
module Rack
|
3
|
+
class PathPrefix < Merb::Rack::Middleware
|
4
|
+
|
5
|
+
def initialize(app, path_prefix = nil)
|
6
|
+
super(app)
|
7
|
+
@path_prefix = /^#{Regexp.escape(path_prefix)}/
|
8
|
+
end
|
9
|
+
|
10
|
+
def deferred?(env)
|
11
|
+
strip_path_prefix(env)
|
12
|
+
@app.deferred?(env)
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(env)
|
16
|
+
strip_path_prefix(env)
|
17
|
+
@app.call(env)
|
18
|
+
end
|
19
|
+
|
20
|
+
def strip_path_prefix(env)
|
21
|
+
['PATH_INFO', 'REQUEST_URI'].each do |path_key|
|
22
|
+
if env[path_key] =~ @path_prefix
|
23
|
+
env[path_key].sub!(@path_prefix, '')
|
24
|
+
env[path_key] = '/' if env[path_key].empty?
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Merb
|
2
|
+
module Rack
|
3
|
+
class Profiler < Merb::Rack::Middleware
|
4
|
+
|
5
|
+
def initialize(app, min=1, iter=1)
|
6
|
+
super(app)
|
7
|
+
@min, @iter = min, iter
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
__profile__("profile_output", @min, @iter) do
|
12
|
+
@app.call(env)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Merb
|
2
|
+
module Rack
|
3
|
+
class Static < Merb::Rack::Middleware
|
4
|
+
|
5
|
+
def initialize(app,directory)
|
6
|
+
super(app)
|
7
|
+
@static_server = ::Rack::File.new(directory)
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
path = env['PATH_INFO'] ? env['PATH_INFO'].chomp('/') : ""
|
12
|
+
cached_path = (path.empty? ? 'index' : path) + '.html'
|
13
|
+
|
14
|
+
if file_exist?(path) && env['REQUEST_METHOD'] =~ /GET|HEAD/ # Serve the file if it's there and the request method is GET or HEAD
|
15
|
+
serve_static(env)
|
16
|
+
elsif file_exist?(cached_path) && env['REQUEST_METHOD'] =~ /GET|HEAD/ # Serve the page cache if it's there and the request method is GET or HEAD
|
17
|
+
env['PATH_INFO'] = cached_path
|
18
|
+
serve_static(env)
|
19
|
+
elsif path =~ /favicon\.ico/
|
20
|
+
return [404, {"Content-Type"=>"text/html"}, "404 Not Found."]
|
21
|
+
else
|
22
|
+
@app.call(env)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# ==== Parameters
|
27
|
+
# path<String>:: The path to the file relative to the server root.
|
28
|
+
#
|
29
|
+
# ==== Returns
|
30
|
+
# Boolean:: True if file exists under the server root and is readable.
|
31
|
+
def file_exist?(path)
|
32
|
+
full_path = ::File.join(@static_server.root, ::Merb::Request.unescape(path))
|
33
|
+
::File.file?(full_path) && ::File.readable?(full_path)
|
34
|
+
end
|
35
|
+
|
36
|
+
# ==== Parameters
|
37
|
+
# env<Hash>:: Environment variables to pass on to the server.
|
38
|
+
def serve_static(env)
|
39
|
+
env["PATH_INFO"] = ::Merb::Request.unescape(env["PATH_INFO"])
|
40
|
+
@static_server.call(env)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/merb-core/server.rb
CHANGED
@@ -22,25 +22,34 @@ module Merb
|
|
22
22
|
@cluster = cluster
|
23
23
|
if @cluster
|
24
24
|
@port.to_i.upto(@port.to_i + @cluster.to_i-1) do |port|
|
25
|
+
pidfile = pid_file(port)
|
26
|
+
pid = IO.read(pidfile).chomp.to_i if File.exist?(pidfile)
|
27
|
+
|
25
28
|
unless alive?(port)
|
26
29
|
remove_pid_file(port)
|
27
|
-
puts "Starting merb server on port
|
30
|
+
puts "Starting merb server on port #{port}, pid file: #{pidfile} and process id is #{pid}" if Merb::Config[:verbose]
|
28
31
|
daemonize(port)
|
29
32
|
else
|
30
|
-
raise "Merb is already running
|
33
|
+
raise "Merb is already running: port is #{port}, pid file: #{pidfile}, process id is #{pid}"
|
31
34
|
end
|
32
35
|
end
|
33
36
|
elsif Merb::Config[:daemonize]
|
37
|
+
pidfile = pid_file(port)
|
38
|
+
pid = IO.read(pidfile).chomp.to_i if File.exist?(pidfile)
|
39
|
+
|
34
40
|
unless alive?(@port)
|
35
41
|
remove_pid_file(@port)
|
42
|
+
puts "Daemonizing..." if Merb::Config[:verbose]
|
36
43
|
daemonize(@port)
|
37
44
|
else
|
38
|
-
raise "Merb is already running
|
45
|
+
raise "Merb is already running: port is #{port}, pid file: #{pidfile}, process id is #{pid}"
|
39
46
|
end
|
40
47
|
else
|
41
48
|
trap('TERM') { exit }
|
42
49
|
trap('INT') { puts "\nExiting"; exit }
|
50
|
+
puts "Running bootloaders..." if Merb::Config[:verbose]
|
43
51
|
BootLoader.run
|
52
|
+
puts "Starting Rack adapter..." if Merb::Config[:verbose]
|
44
53
|
Merb.adapter.start(Merb::Config.to_hash)
|
45
54
|
end
|
46
55
|
end
|
@@ -52,8 +61,11 @@ module Merb
|
|
52
61
|
# Boolean::
|
53
62
|
# True if Merb is running on the specified port.
|
54
63
|
def alive?(port)
|
64
|
+
puts "About to check if port #{port} is alive..." if Merb::Config[:verbose]
|
55
65
|
pidfile = pid_file(port)
|
66
|
+
puts "Pidfile is #{pidfile}..." if Merb::Config[:verbose]
|
56
67
|
pid = IO.read(pidfile).chomp.to_i
|
68
|
+
puts "Process id is #{pid}" if Merb::Config[:verbose]
|
57
69
|
Process.kill(0, pid)
|
58
70
|
true
|
59
71
|
rescue
|
@@ -72,8 +84,8 @@ module Merb
|
|
72
84
|
begin
|
73
85
|
pidfiles = port == "all" ?
|
74
86
|
pid_files : [ pid_file(port) ]
|
75
|
-
|
76
|
-
pidfiles.each do |f|
|
87
|
+
|
88
|
+
pidfiles.each do |f|
|
77
89
|
pid = IO.read(f).chomp.to_i
|
78
90
|
begin
|
79
91
|
Process.kill(sig, pid)
|
@@ -98,6 +110,7 @@ module Merb
|
|
98
110
|
# ==== Parameters
|
99
111
|
# port<~to_s>:: The port of the Merb process to daemonize.
|
100
112
|
def daemonize(port)
|
113
|
+
puts "About to fork..." if Merb::Config[:verbose]
|
101
114
|
fork do
|
102
115
|
Process.setsid
|
103
116
|
exit if fork
|
@@ -117,13 +130,15 @@ module Merb
|
|
117
130
|
def change_privilege
|
118
131
|
if Merb::Config[:user]
|
119
132
|
if Merb::Config[:group]
|
133
|
+
puts "About to change privilege to group #{Merb::Config[:group]} and user #{Merb::Config[:user]}" if Merb::Config[:verbose]
|
120
134
|
_change_privilege(Merb::Config[:user], Merb::Config[:group])
|
121
135
|
else
|
136
|
+
puts "About to change privilege to user #{Merb::Config[:user]}" if Merb::Config[:verbose]
|
122
137
|
_change_privilege(Merb::Config[:user])
|
123
138
|
end
|
124
139
|
end
|
125
140
|
end
|
126
|
-
|
141
|
+
|
127
142
|
# Removes a PID file used by the server from the filesystem.
|
128
143
|
# This uses :pid_file options from configuration when provided
|
129
144
|
# or merb.<port>.pid in log directory by default.
|
@@ -137,6 +152,7 @@ module Merb
|
|
137
152
|
# instead of the port based PID file.
|
138
153
|
def remove_pid_file(port)
|
139
154
|
pidfile = pid_file(port)
|
155
|
+
puts "Removing pid file #{pidfile} (port is #{port})..."
|
140
156
|
FileUtils.rm(pidfile) if File.exist?(pidfile)
|
141
157
|
end
|
142
158
|
|
@@ -153,10 +169,12 @@ module Merb
|
|
153
169
|
# instead of the port based PID file.
|
154
170
|
def store_pid(port)
|
155
171
|
pidfile = pid_file(port)
|
172
|
+
puts "Storing pid file to #{pidfile}..."
|
156
173
|
FileUtils.mkdir_p(File.dirname(pidfile)) unless File.directory?(File.dirname(pidfile))
|
174
|
+
puts "Created directory, writing process id..." if Merb::Config[:verbose]
|
157
175
|
File.open(pidfile, 'w'){ |f| f.write("#{Process.pid}") }
|
158
176
|
end
|
159
|
-
|
177
|
+
|
160
178
|
# Gets the pid file for the specified port.
|
161
179
|
#
|
162
180
|
# ==== Parameters
|
@@ -202,8 +220,8 @@ module Merb
|
|
202
220
|
else
|
203
221
|
Dir[Merb.log_path / "merb.*.pid"]
|
204
222
|
end
|
205
|
-
end
|
206
|
-
|
223
|
+
end
|
224
|
+
|
207
225
|
# Change privileges of the process to the specified user and group.
|
208
226
|
#
|
209
227
|
# ==== Parameters
|
@@ -0,0 +1,68 @@
|
|
1
|
+
namespace :audit do
|
2
|
+
|
3
|
+
desc "Print out the named and anonymous routes"
|
4
|
+
task :routes => :merb_env do
|
5
|
+
seen = []
|
6
|
+
unless Merb::Router.named_routes.empty?
|
7
|
+
puts "Named Routes"
|
8
|
+
Merb::Router.named_routes.each do |name,route|
|
9
|
+
puts " #{name}: #{route}"
|
10
|
+
seen << route
|
11
|
+
end
|
12
|
+
end
|
13
|
+
puts "Anonymous Routes"
|
14
|
+
(Merb::Router.routes - seen).each do |route|
|
15
|
+
puts " #{route}"
|
16
|
+
end
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "Print out all controllers"
|
21
|
+
task :controllers => :merb_env do
|
22
|
+
puts "\nControllers:\n\n"
|
23
|
+
abstract_controller_classes.each do |klass|
|
24
|
+
if klass.respond_to?(:subclasses_list)
|
25
|
+
puts "#{klass} < #{klass.superclass}"
|
26
|
+
subklasses = klass.subclasses_list.sort.map { |x| Object.full_const_get(x) }
|
27
|
+
unless subklasses.empty?
|
28
|
+
subklasses.each { |subklass| puts "- #{subklass}" }
|
29
|
+
else
|
30
|
+
puts "~ no subclasses"
|
31
|
+
end
|
32
|
+
puts
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "Print out controllers and their actions (use CONTROLLER=Foo,Bar to be selective)"
|
38
|
+
task :actions => :merb_env do
|
39
|
+
puts "\nControllers and their actions:\n\n"
|
40
|
+
filter_controllers = ENV['CONTROLLER'] ? ENV['CONTROLLER'].split(',') : nil
|
41
|
+
abstract_controllers = abstract_controller_classes
|
42
|
+
classes = Merb::AbstractController.subclasses_list.sort.map { |x| Object.full_const_get(x) }
|
43
|
+
classes = classes.select { |k| k.name.in?(filter_controllers) } if filter_controllers
|
44
|
+
classes.each do |subklass|
|
45
|
+
next if subklass.in?(abstract_controllers) || !subklass.respond_to?(:callable_actions)
|
46
|
+
puts "#{subklass} < #{subklass.superclass}"
|
47
|
+
unless subklass.callable_actions.empty?
|
48
|
+
subklass.callable_actions.sort.each do |action, null|
|
49
|
+
if subklass.respond_to?(:action_argument_list)
|
50
|
+
arguments, defaults = subklass.action_argument_list[action]
|
51
|
+
args = arguments.map { |name, value| value ? "#{name} = #{value.inspect}" : name.to_s }.join(', ')
|
52
|
+
puts args.empty? ? "- #{action}" : "- #{action}(#{args})"
|
53
|
+
else
|
54
|
+
puts "- #{action}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
else
|
58
|
+
puts "~ no callable actions"
|
59
|
+
end
|
60
|
+
puts
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def abstract_controller_classes
|
65
|
+
ObjectSpace.classes.select { |x| x.superclass == Merb::AbstractController }.sort_by { |x| x.name }
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Dir[File.dirname(__FILE__) / '*.rake'].each { |ext| load ext }
|
@@ -0,0 +1,71 @@
|
|
1
|
+
def show_line(name, stats, color = nil)
|
2
|
+
ce = color ? "\033[0m" : ""
|
3
|
+
puts "| #{color}#{name.to_s.capitalize.ljust(20)}#{ce} " +
|
4
|
+
"| #{color}#{stats[:lines].to_s.rjust(7)}#{ce} " +
|
5
|
+
"| #{color}#{stats[:loc].to_s.rjust(7)}#{ce} " +
|
6
|
+
"| #{color}#{stats[:classes].to_s.rjust(7)}#{ce} " +
|
7
|
+
"| #{color}#{stats[:modules].to_s.rjust(7)}#{ce} " +
|
8
|
+
"| #{color}#{stats[:methods].to_s.rjust(7)}#{ce} |"
|
9
|
+
puts separator
|
10
|
+
end
|
11
|
+
|
12
|
+
def separator
|
13
|
+
'+----------------------+---------+---------+---------+---------+---------+'
|
14
|
+
end
|
15
|
+
|
16
|
+
def check_dir(dir)
|
17
|
+
Dir.foreach(dir) do |file_name|
|
18
|
+
if File.stat(dir / file_name).directory? and (/^\./ !~ file_name)
|
19
|
+
check_dir(dir / file_name)
|
20
|
+
end
|
21
|
+
|
22
|
+
if file_name =~ /.*\.rb$/
|
23
|
+
File.open(dir / file_name).each_line do |line|
|
24
|
+
@stats[:lines] += 1
|
25
|
+
@stats[:loc] += 1 unless line =~ /^\s*$/ || line =~ /^\s*#/
|
26
|
+
@stats[:classes] += 1 if line =~ /class [A-Z]/
|
27
|
+
@stats[:modules] += 1 if line =~ /module [A-Z]/
|
28
|
+
@stats[:methods] += 1 if line =~ /def [a-z]/
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "Lines of code statistics"
|
35
|
+
task :stats do
|
36
|
+
STATISTICS_DIRS = {
|
37
|
+
:controllers => 'app/controllers',
|
38
|
+
:helpers => 'app/helpers',
|
39
|
+
:models => 'app/models',
|
40
|
+
:lib => 'lib',
|
41
|
+
:spec => 'spec'
|
42
|
+
}
|
43
|
+
EMPTY_STATS = { :lines => 0, :loc => 0, :classes => 0, :modules => 0, :methods => 0 }
|
44
|
+
|
45
|
+
@all = {}
|
46
|
+
total = EMPTY_STATS.clone
|
47
|
+
ce = "\033[0m"
|
48
|
+
cb = "\033[35m"
|
49
|
+
cg = "\033[4;32m"
|
50
|
+
cr = "\033[31m"
|
51
|
+
|
52
|
+
puts separator
|
53
|
+
puts "| #{cg}Name#{ce} | #{cg}Lines#{ce} | #{cg}LOC#{ce} | #{cg}Classes#{ce} | #{cg}Modules#{ce} | #{cg}Methods#{ce} |"
|
54
|
+
puts separator
|
55
|
+
|
56
|
+
STATISTICS_DIRS.each_pair do |name, dir|
|
57
|
+
@stats = EMPTY_STATS.clone
|
58
|
+
check_dir(dir)
|
59
|
+
@all[name] = @stats
|
60
|
+
show_line(name, @stats)
|
61
|
+
@stats.each_pair { |type, count| total[type] += count }
|
62
|
+
end
|
63
|
+
|
64
|
+
show_line('Total', total, cr)
|
65
|
+
|
66
|
+
code_loc = [:controllers, :helpers, :models].inject(0) { |sum, e| sum += @all[e][:loc] }
|
67
|
+
test_loc = @all[:spec][:loc]
|
68
|
+
|
69
|
+
puts " Code LOC: #{cb}#{code_loc}#{ce} Test LOC: #{cb}#{test_loc}#{ce} Test to code radio: #{cb}1:%0.2f#{ce}" % (test_loc.to_f / code_loc.to_f)
|
70
|
+
puts
|
71
|
+
end
|
data/lib/merb-core/test.rb
CHANGED
@@ -2,9 +2,10 @@ require "hpricot"
|
|
2
2
|
|
3
3
|
require 'merb-core/test/test_ext/hpricot'
|
4
4
|
require 'merb-core/test/test_ext/object'
|
5
|
+
require 'merb-core/test/test_ext/string'
|
5
6
|
|
6
7
|
module Merb; module Test; end; end
|
7
8
|
|
8
9
|
require 'merb-core/test/helpers'
|
9
10
|
|
10
|
-
require 'merb-core/test/matchers'
|
11
|
+
require 'merb-core/test/matchers'
|
@@ -97,8 +97,8 @@ module Merb::Test::MultipartRequestHelper
|
|
97
97
|
# &blk:: The block is executed in the context of the controller.
|
98
98
|
#
|
99
99
|
# ==== Example
|
100
|
-
# dispatch_multipart_to(MyController, :create, :my_file => @a_file ) do
|
101
|
-
#
|
100
|
+
# dispatch_multipart_to(MyController, :create, :my_file => @a_file ) do |controller|
|
101
|
+
# controller.stub!(:current_user).and_return(@user)
|
102
102
|
# end
|
103
103
|
#
|
104
104
|
# ==== Notes
|
@@ -172,4 +172,4 @@ module Merb::Test::MultipartRequestHelper
|
|
172
172
|
:content_length => body.length), :post_body => body)
|
173
173
|
end
|
174
174
|
end
|
175
|
-
end
|
175
|
+
end
|
@@ -87,8 +87,8 @@ module Merb
|
|
87
87
|
# the action being dispatched.
|
88
88
|
#
|
89
89
|
# ==== Example
|
90
|
-
# dispatch_to(MyController, :create, :name => 'Homer' ) do
|
91
|
-
#
|
90
|
+
# dispatch_to(MyController, :create, :name => 'Homer' ) do |controller|
|
91
|
+
# controller.stub!(:current_user).and_return(@user)
|
92
92
|
# end
|
93
93
|
#
|
94
94
|
# ==== Notes
|
@@ -97,12 +97,8 @@ module Merb
|
|
97
97
|
#---
|
98
98
|
# @public
|
99
99
|
def dispatch_to(controller_klass, action, params = {}, env = {}, &blk)
|
100
|
-
|
101
|
-
|
102
|
-
request = fake_request(env.merge(
|
103
|
-
:query_string => Merb::Request.params_to_query_string(params)), request_body)
|
104
|
-
|
105
|
-
dispatch_request(request, controller_klass, action, &blk)
|
100
|
+
params = merge_controller_and_action(controller_klass, action, params)
|
101
|
+
dispatch_request(build_request(params, env), controller_klass, action.to_s, &blk)
|
106
102
|
end
|
107
103
|
|
108
104
|
|
@@ -126,8 +122,8 @@ module Merb
|
|
126
122
|
# the action being dispatched.
|
127
123
|
#
|
128
124
|
# ==== Example
|
129
|
-
# dispatch_with_basic_authentication_to(MyController, :create, 'Fred', 'secret', :name => 'Homer' ) do
|
130
|
-
#
|
125
|
+
# dispatch_with_basic_authentication_to(MyController, :create, 'Fred', 'secret', :name => 'Homer' ) do |controller|
|
126
|
+
# controller.stub!(:current_user).and_return(@user)
|
131
127
|
# end
|
132
128
|
#
|
133
129
|
# ==== Notes
|
@@ -136,13 +132,47 @@ module Merb
|
|
136
132
|
#---
|
137
133
|
# @public
|
138
134
|
def dispatch_with_basic_authentication_to(controller_klass, action, username, password, params = {}, env = {}, &blk)
|
139
|
-
action = action.to_s
|
140
|
-
request_body = { :post_body => env[:post_body], :req => env[:req] }
|
141
135
|
env["X_HTTP_AUTHORIZATION"] = "Basic #{Base64.encode64("#{username}:#{password}")}"
|
142
|
-
|
143
|
-
|
136
|
+
|
137
|
+
params = merge_controller_and_action(controller_klass, action, params)
|
138
|
+
dispatch_request(build_request(params, env), controller_klass, action.to_s, &blk)
|
139
|
+
end
|
140
|
+
|
141
|
+
def merge_controller_and_action(controller_klass, action, params)
|
142
|
+
params[:controller] = controller_klass.name.to_const_path
|
143
|
+
params[:action] = action.to_s
|
144
|
+
|
145
|
+
params
|
146
|
+
end
|
144
147
|
|
145
|
-
|
148
|
+
# Prepares and returns a request suitable for dispatching with
|
149
|
+
# dispatch_request. If you don't need to modify the request
|
150
|
+
# object before dispatching (e.g. to add cookies), you probably
|
151
|
+
# want to use dispatch_to instead.
|
152
|
+
#
|
153
|
+
# ==== Parameters
|
154
|
+
# params<Hash>::
|
155
|
+
# An optional hash that will end up as params in the controller instance.
|
156
|
+
# env<Hash>::
|
157
|
+
# An optional hash that is passed to the fake request. Any request options
|
158
|
+
# should go here (see +fake_request+), including :req or :post_body
|
159
|
+
# for setting the request body itself.
|
160
|
+
#
|
161
|
+
# ==== Example
|
162
|
+
# req = build_request(:id => 1)
|
163
|
+
# req.cookies['app_cookie'] = "testing"
|
164
|
+
# dispatch_request(req, MyController, :edit)
|
165
|
+
#
|
166
|
+
# ==== Notes
|
167
|
+
# Does not use routes.
|
168
|
+
#
|
169
|
+
#---
|
170
|
+
# @public
|
171
|
+
def build_request(params = {}, env = {})
|
172
|
+
params = Merb::Request.params_to_query_string(params)
|
173
|
+
env[:query_string] = env["QUERY_STRING"] ? "#{env["QUERY_STRING"]}&#{params}" : params
|
174
|
+
|
175
|
+
fake_request(env, { :post_body => env[:post_body], :req => env[:req] })
|
146
176
|
end
|
147
177
|
|
148
178
|
# An HTTP GET request that operates through the router.
|
@@ -157,6 +187,8 @@ module Merb
|
|
157
187
|
# &blk::
|
158
188
|
# The controller is yielded to the block provided for actions *prior* to
|
159
189
|
# the action being dispatched.
|
190
|
+
#---
|
191
|
+
# @public
|
160
192
|
def get(path, params = {}, env = {}, &block)
|
161
193
|
env[:request_method] = "GET"
|
162
194
|
request(path, params, env, &block)
|
@@ -174,6 +206,8 @@ module Merb
|
|
174
206
|
# &blk::
|
175
207
|
# The controller is yielded to the block provided for actions *prior* to
|
176
208
|
# the action being dispatched.
|
209
|
+
#---
|
210
|
+
# @public
|
177
211
|
def post(path, params = {}, env = {}, &block)
|
178
212
|
env[:request_method] = "POST"
|
179
213
|
request(path, params, env, &block)
|
@@ -191,6 +225,8 @@ module Merb
|
|
191
225
|
# &blk::
|
192
226
|
# The controller is yielded to the block provided for actions *prior* to
|
193
227
|
# the action being dispatched.
|
228
|
+
#---
|
229
|
+
# @public
|
194
230
|
def put(path, params = {}, env = {}, &block)
|
195
231
|
env[:request_method] = "PUT"
|
196
232
|
request(path, params, env, &block)
|
@@ -208,6 +244,8 @@ module Merb
|
|
208
244
|
# &blk::
|
209
245
|
# The controller is yielded to the block provided for actions *prior* to
|
210
246
|
# the action being dispatched.
|
247
|
+
#---
|
248
|
+
# @public
|
211
249
|
def delete(path, params = {}, env = {}, &block)
|
212
250
|
env[:request_method] = "DELETE"
|
213
251
|
request(path, params, env, &block)
|
@@ -228,8 +266,8 @@ module Merb
|
|
228
266
|
# the action being dispatched.
|
229
267
|
#
|
230
268
|
# ==== Example
|
231
|
-
# request(path, { :name => 'Homer' }, { :request_method => "PUT" }) do
|
232
|
-
#
|
269
|
+
# request(path, { :name => 'Homer' }, { :request_method => "PUT" }) do |controller|
|
270
|
+
# controller.stub!(:current_user).and_return(@user)
|
233
271
|
# end
|
234
272
|
#
|
235
273
|
# ==== Notes
|
@@ -239,7 +277,8 @@ module Merb
|
|
239
277
|
# @semi-public
|
240
278
|
def request(path, params = {}, env= {}, &block)
|
241
279
|
env[:request_method] ||= "GET"
|
242
|
-
env[:request_uri] = path
|
280
|
+
env[:request_uri], env[:query_string] = path.split('?')
|
281
|
+
|
243
282
|
multipart = env.delete(:test_with_multipart)
|
244
283
|
|
245
284
|
request = fake_request(env)
|
@@ -274,7 +313,7 @@ module Merb
|
|
274
313
|
# Does not use routes.
|
275
314
|
#
|
276
315
|
#---
|
277
|
-
# @
|
316
|
+
# @public
|
278
317
|
def dispatch_request(request, controller_klass, action, &blk)
|
279
318
|
controller = controller_klass.new(request)
|
280
319
|
yield controller if block_given?
|
@@ -298,14 +337,17 @@ module Merb
|
|
298
337
|
#
|
299
338
|
# ==== Returns
|
300
339
|
# Hash:: The parameters built based on the matching route.
|
340
|
+
#
|
341
|
+
#---
|
342
|
+
# @semi-public
|
301
343
|
def check_request_for_route(request)
|
302
344
|
match = ::Merb::Router.match(request)
|
303
|
-
if match[0].nil?
|
345
|
+
if match[0].nil? && match[1].empty?
|
304
346
|
raise ::Merb::ControllerExceptions::BadRequest, "No routes match the request"
|
305
347
|
else
|
306
348
|
match[1]
|
307
349
|
end
|
308
|
-
end
|
309
|
-
end
|
310
|
-
end
|
311
|
-
end
|
350
|
+
end # check_request_for_route
|
351
|
+
end # RequestHelper
|
352
|
+
end # Test
|
353
|
+
end # Merb
|