manveru-ramaze 2008.12 → 2009.01
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/proto/public/.htaccess +24 -0
- data/lib/ramaze/action/render.rb +6 -5
- data/lib/ramaze/controller/resolve.rb +2 -2
- data/lib/ramaze/current/request.rb +2 -2
- data/lib/ramaze/helper/bench.rb +43 -0
- data/lib/ramaze/helper/markaby.rb +1 -1
- data/lib/ramaze/helper/paginate.rb +1 -1
- data/lib/ramaze/option.rb +1 -1
- data/lib/ramaze/reloader/watch_inotify.rb +42 -30
- data/lib/ramaze/reloader/watch_stat.rb +1 -5
- data/lib/ramaze/reloader.rb +1 -1
- data/lib/ramaze/version.rb +1 -1
- data/ramaze.gemspec +3 -167
- metadata +4 -168
@@ -0,0 +1,24 @@
|
|
1
|
+
# General Apache options
|
2
|
+
Options +FollowSymLinks +ExecCGI
|
3
|
+
AddHandler cgi-script cgi rb
|
4
|
+
<IfModule mod_fastcgi.c>
|
5
|
+
AddHandler fastcgi-script fcgi
|
6
|
+
</IfModule>
|
7
|
+
<IfModule mod_fcgid.c>
|
8
|
+
AddHandler fcgid-script fcgi
|
9
|
+
</IfModule>
|
10
|
+
|
11
|
+
# Redirect all requests not available on the filesystem to Ramaze.
|
12
|
+
|
13
|
+
RewriteEngine On
|
14
|
+
RewriteCond %{REQUEST_FILENAME} !-f
|
15
|
+
RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]
|
16
|
+
|
17
|
+
# In case Ramaze experiences terminal errors.
|
18
|
+
# Instead of displaying this message you can supply a
|
19
|
+
# file here which will be rendered instead.
|
20
|
+
#
|
21
|
+
# Example:
|
22
|
+
# ErrorDocument 500 /500.html
|
23
|
+
|
24
|
+
ErrorDocument 500 "<h2>Application error</h2>Ramaze failed to start properly"
|
data/lib/ramaze/action/render.rb
CHANGED
@@ -49,8 +49,8 @@ module Ramaze
|
|
49
49
|
# true.
|
50
50
|
|
51
51
|
def cached_render
|
52
|
-
if Global.file_cache
|
53
|
-
cached_render_file
|
52
|
+
if cache_root = Global.file_cache
|
53
|
+
cached_render_file(cache_root)
|
54
54
|
else
|
55
55
|
cached_render_memory
|
56
56
|
end
|
@@ -59,12 +59,13 @@ module Ramaze
|
|
59
59
|
# Uses files in the Global.public_root to provide a static ressource on
|
60
60
|
# next request and returns the rendered action
|
61
61
|
|
62
|
-
def cached_render_file
|
62
|
+
def cached_render_file(cache_root)
|
63
63
|
rendered = uncached_render
|
64
64
|
|
65
|
-
|
65
|
+
cr = cache_root.respond_to?(:to_str) ? cache_root.to_str : Global.public_root
|
66
|
+
global_epath = File.join(cr, self.controller.mapping, extended_path)
|
66
67
|
FileUtils.mkdir_p(File.dirname(global_epath))
|
67
|
-
File.open(global_epath, 'w+')
|
68
|
+
File.open(global_epath, 'w+'){|fp| fp.print(rendered) }
|
68
69
|
|
69
70
|
rendered
|
70
71
|
end
|
@@ -16,7 +16,7 @@ module Ramaze
|
|
16
16
|
# instead, in either case with path as argument.
|
17
17
|
|
18
18
|
def resolve(path, routed = false)
|
19
|
-
|
19
|
+
Thread.current[:routed] = routed
|
20
20
|
|
21
21
|
FILTER.each do |filter|
|
22
22
|
answer = if filter.respond_to?(:call)
|
@@ -90,7 +90,7 @@ module Ramaze
|
|
90
90
|
end
|
91
91
|
end
|
92
92
|
|
93
|
-
if
|
93
|
+
if !Thread.current[:routed] and new_path = Route.resolve(path)
|
94
94
|
Log.dev("Routing from `#{path}' to `#{new_path}'")
|
95
95
|
return resolve(new_path, true)
|
96
96
|
end
|
@@ -196,9 +196,9 @@ module Ramaze
|
|
196
196
|
# Example:
|
197
197
|
# request.params
|
198
198
|
# # => {'name' => 'jason', 'age' => '45', 'job' => 'lumberjack'}
|
199
|
-
# request.
|
199
|
+
# request.subset('name')
|
200
200
|
# # => {'name' => 'jason'}
|
201
|
-
# request.
|
201
|
+
# request.subset(:name, :job)
|
202
202
|
# # => {'name' => 'jason', 'job' => 'lumberjack'}
|
203
203
|
|
204
204
|
def subset(*keys)
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
|
3
|
+
module Ramaze
|
4
|
+
module Helper
|
5
|
+
|
6
|
+
# Little helper to give you a hand when benching parts of actions
|
7
|
+
|
8
|
+
module Bench
|
9
|
+
|
10
|
+
# Will first run an empty loop to determine the overhead it imposes, then
|
11
|
+
# goes on to yield your block +iterations+ times.
|
12
|
+
#
|
13
|
+
# The last yielded return value will be returned upon completion of the
|
14
|
+
# benchmark and the result of the benchmark itself will be sent to
|
15
|
+
# Log.info
|
16
|
+
#
|
17
|
+
# Example:
|
18
|
+
#
|
19
|
+
# class MainController < Ramaze::Controller
|
20
|
+
# def index
|
21
|
+
# @users = bench{ User.all }
|
22
|
+
# @tags = bench{ Article.tags }
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# This will show something like following in your log:
|
27
|
+
# [..] INFO Bench ./start.rb:3:in `index': 0.121163845062256
|
28
|
+
# [..] INFO Bench ./start.rb:4:in `index': 2.234987235098341
|
29
|
+
#
|
30
|
+
# So now we know that the Article.tags call takes the most time and
|
31
|
+
# should be improved.
|
32
|
+
|
33
|
+
def bench(iterations = 1)
|
34
|
+
result = nil
|
35
|
+
from = caller[0]
|
36
|
+
delta = Benchmark.realtime{ iterations.times{ nil }}
|
37
|
+
taken = Benchmark.realtime{ iterations.times{ result = yield }}
|
38
|
+
Log.info "Bench #{from}: #{taken - delta}"
|
39
|
+
return result
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -15,7 +15,7 @@ module Ramaze
|
|
15
15
|
def markaby(ivs = {}, helpers = nil, &block)
|
16
16
|
builder = ::Markaby::Builder
|
17
17
|
builder.extend(Ramaze::Helper::Methods)
|
18
|
-
builder.send(:helper, :link)
|
18
|
+
builder.send(:helper, :redirect, :link, :sendfile, :flash, :cgi, :partial)
|
19
19
|
|
20
20
|
iv_hash = {}
|
21
21
|
instance_variables.each do |iv|
|
@@ -165,7 +165,7 @@ module Ramaze
|
|
165
165
|
text = h(text.to_s)
|
166
166
|
|
167
167
|
params = Ramaze::Request.current.params.merge(@var.to_s => n)
|
168
|
-
name = Ramaze::Request.current.
|
168
|
+
name = Ramaze::Request.current.path_info
|
169
169
|
hash[:href] = R(name, params)
|
170
170
|
|
171
171
|
g.a(hash){ text }
|
data/lib/ramaze/option.rb
CHANGED
@@ -78,7 +78,7 @@ module Ramaze
|
|
78
78
|
o "Turn on customized error pages. Use Rack::ShowException otherwise.",
|
79
79
|
:error_page, true, :cli => true
|
80
80
|
|
81
|
-
o "
|
81
|
+
o "Cache actions to filesystem, uses String as directory name or Global.public_root if other truism",
|
82
82
|
:file_cache, false, :cli => false
|
83
83
|
|
84
84
|
o "Specify what IP Ramaze will respond to - 0.0.0.0 for all",
|
@@ -1,57 +1,62 @@
|
|
1
1
|
module Ramaze
|
2
2
|
class Reloader
|
3
|
+
# TODO:
|
4
|
+
# * There seems to be a problem somewhere that I couldn't identify yet, a
|
5
|
+
# file has to be modified twice initially to make it show up as
|
6
|
+
# modified here, subsequent changes work just fine.
|
7
|
+
# The only workaround I could find right now would be to read/write
|
8
|
+
# every single file, but that would be unexpected, irresponsible, and
|
9
|
+
# error-prone.
|
10
|
+
#
|
11
|
+
# NOTE:
|
12
|
+
# * I have changed from using a Mutex to using a Queue, which uses a
|
13
|
+
# Mutex internally.
|
14
|
+
|
3
15
|
class WatchInotify
|
4
16
|
POLL_INTERVAL = 2 # seconds
|
17
|
+
NOTIFY_MASK = RInotify::MODIFY | RInotify::IN_ONESHOT
|
5
18
|
|
6
19
|
def initialize
|
7
20
|
@watcher = RInotify.new
|
8
|
-
@changed =
|
9
|
-
@mutex = Mutex.new
|
21
|
+
@changed = Queue.new
|
10
22
|
@watcher_thread = start_watcher
|
11
23
|
end
|
12
24
|
|
13
25
|
def call(cooldown)
|
14
|
-
yield
|
26
|
+
yield
|
15
27
|
end
|
16
28
|
|
17
29
|
# TODO: define a finalizer to cleanup? -- reloader never calls #close
|
18
30
|
|
19
31
|
def start_watcher
|
20
|
-
Thread.new
|
21
|
-
loop do
|
22
|
-
watcher_cycle
|
23
|
-
sleep POLL_INTERVAL
|
24
|
-
end
|
25
|
-
end
|
32
|
+
Thread.new{ loop{ watcher_cycle }}
|
26
33
|
end
|
27
34
|
|
35
|
+
# Not much work here, we just have to empty the event queue and push the
|
36
|
+
# descriptors for reloading on next request.
|
28
37
|
def watcher_cycle
|
29
|
-
return unless @watcher.wait_for_events(
|
30
|
-
changed_descriptors = []
|
38
|
+
return unless @watcher.wait_for_events(POLL_INTERVAL)
|
31
39
|
|
32
40
|
@watcher.each_event do |event|
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
@mutex.synchronize do
|
37
|
-
changed_descriptors.each do |descriptor|
|
38
|
-
@changed << @watcher.watch_descriptors[descriptor]
|
39
|
-
end
|
41
|
+
@changed.push(event.watch_descriptor)
|
40
42
|
end
|
41
43
|
end
|
42
44
|
|
43
45
|
def watch(file)
|
44
|
-
return
|
45
|
-
return
|
46
|
+
return if @watcher.watch_descriptors.has_value?(file)
|
47
|
+
return unless File.exist?(file)
|
46
48
|
|
47
|
-
@
|
48
|
-
|
49
|
-
|
49
|
+
@watcher.add_watch(file, NOTIFY_MASK)
|
50
|
+
rescue Errno::ENOENT
|
51
|
+
retry
|
50
52
|
end
|
51
53
|
|
54
|
+
# FIXME:
|
55
|
+
# Seems like this won't work due to some bug in the rinotify library.
|
56
|
+
# Would be cool if someone could make a FFI version.
|
57
|
+
|
52
58
|
def remove_watch(file)
|
53
|
-
@
|
54
|
-
true
|
59
|
+
@watcher.rm_watch(file)
|
55
60
|
end
|
56
61
|
|
57
62
|
def close
|
@@ -60,13 +65,20 @@ module Ramaze
|
|
60
65
|
true
|
61
66
|
end
|
62
67
|
|
68
|
+
# NOTE:
|
69
|
+
# We have to add the changed file again after we got a notification, I
|
70
|
+
# have no idea why, but using IN_ONESHOT should make sure that there is
|
71
|
+
# no memory leak in the C level even if we add a file again.
|
72
|
+
# There is a memory leak however in the watch_descriptors hash, since
|
73
|
+
# rinotify won't synchronize the contents properly and will only add to
|
74
|
+
# the hash, so we have to clean up ourselves.
|
63
75
|
def changed_files
|
64
|
-
@
|
65
|
-
|
66
|
-
|
76
|
+
until @changed.empty?
|
77
|
+
descriptor = @changed.shift
|
78
|
+
file = @watcher.watch_descriptors.delete(descriptor)
|
79
|
+
watch(file)
|
80
|
+
yield(file)
|
67
81
|
end
|
68
|
-
@tmp.uniq!
|
69
|
-
@tmp
|
70
82
|
end
|
71
83
|
end
|
72
84
|
end
|
@@ -38,18 +38,14 @@ module Ramaze
|
|
38
38
|
|
39
39
|
# return files changed since last call
|
40
40
|
def changed_files
|
41
|
-
changed = []
|
42
|
-
|
43
41
|
@files.each do |file, stat|
|
44
42
|
if new_stat = safe_stat(file)
|
45
43
|
if new_stat.mtime > stat.mtime
|
46
|
-
changed << file
|
47
44
|
@files[file] = new_stat
|
45
|
+
yield(file)
|
48
46
|
end
|
49
47
|
end
|
50
48
|
end
|
51
|
-
|
52
|
-
changed
|
53
49
|
end
|
54
50
|
|
55
51
|
def safe_stat(file)
|
data/lib/ramaze/reloader.rb
CHANGED
data/lib/ramaze/version.rb
CHANGED