ramaze 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +14 -29
- data/bin/ramaze +2 -3
- data/doc/AUTHORS +5 -2
- data/doc/CHANGELOG +262 -9
- data/doc/FAQ +6 -6
- data/doc/meta/announcement.txt +5 -19
- data/doc/tutorial/todolist.html +47 -57
- data/doc/tutorial/todolist.mkd +47 -55
- data/examples/memleak_detector.rb +31 -0
- data/examples/todolist/src/controller/main.rb +14 -13
- data/examples/todolist/src/element/page.rb +2 -2
- data/examples/todolist/src/model.rb +2 -2
- data/examples/todolist/todolist.db +0 -4
- data/examples/whywiki/main.rb +2 -2
- data/examples/whywiki/template/edit.xhtml +1 -1
- data/examples/whywiki/template/show.xhtml +3 -3
- data/lib/proto/src/controller/main.rb +18 -1
- data/lib/proto/template/index.xhtml +11 -2
- data/lib/ramaze.rb +1 -1
- data/lib/ramaze/action.rb +104 -5
- data/lib/ramaze/action/render.rb +54 -0
- data/lib/ramaze/adapter.rb +2 -1
- data/lib/ramaze/adapter/mongrel.rb +13 -4
- data/lib/ramaze/cache.rb +17 -8
- data/lib/ramaze/cache/memcached.rb +1 -5
- data/lib/ramaze/controller.rb +51 -18
- data/lib/ramaze/controller/resolve.rb +19 -14
- data/lib/ramaze/dispatcher.rb +13 -16
- data/lib/ramaze/dispatcher/action.rb +2 -3
- data/lib/ramaze/dispatcher/error.rb +8 -3
- data/lib/ramaze/dispatcher/file.rb +1 -4
- data/lib/ramaze/error.rb +5 -5
- data/lib/ramaze/global.rb +7 -1
- data/lib/ramaze/global/globalstruct.rb +1 -3
- data/lib/ramaze/helper/aspect.rb +8 -10
- data/lib/ramaze/helper/cgi.rb +21 -3
- data/lib/ramaze/helper/identity.rb +4 -6
- data/lib/ramaze/helper/link.rb +4 -4
- data/lib/ramaze/helper/pager.rb +316 -0
- data/lib/ramaze/helper/partial.rb +37 -0
- data/lib/ramaze/helper/stack.rb +1 -1
- data/lib/ramaze/inform.rb +9 -0
- data/lib/ramaze/inform/hub.rb +5 -0
- data/lib/ramaze/inform/informer.rb +12 -6
- data/lib/ramaze/inform/informing.rb +32 -7
- data/lib/ramaze/inform/knotify.rb +21 -0
- data/lib/ramaze/inform/xosd.rb +58 -24
- data/lib/ramaze/sourcereload.rb +30 -1
- data/lib/ramaze/template.rb +33 -12
- data/lib/ramaze/template/amrita2.rb +21 -20
- data/lib/ramaze/template/erubis.rb +18 -14
- data/lib/ramaze/template/ezamar.rb +15 -26
- data/lib/ramaze/template/ezamar/element.rb +1 -1
- data/lib/ramaze/template/ezamar/engine.rb +45 -36
- data/lib/ramaze/template/ezamar/morpher.rb +3 -3
- data/lib/ramaze/template/ezamar/render_partial.rb +26 -0
- data/lib/ramaze/template/haml.rb +23 -18
- data/lib/ramaze/template/liquid.rb +5 -3
- data/lib/ramaze/template/markaby.rb +14 -11
- data/lib/ramaze/template/remarkably.rb +11 -5
- data/lib/ramaze/tool/localize.rb +12 -4
- data/lib/ramaze/tool/tidy.rb +26 -23
- data/lib/ramaze/trinity/request.rb +11 -7
- data/lib/ramaze/trinity/session.rb +24 -8
- data/lib/ramaze/version.rb +1 -1
- data/rake_tasks/maintaince.rake +136 -11
- data/spec/examples/templates/template_liquid.rb +6 -3
- data/spec/examples/todolist.rb +1 -2
- data/spec/helper/minimal.rb +7 -7
- data/spec/ramaze/action/basics.rb +19 -0
- data/spec/ramaze/action/render.rb +18 -0
- data/spec/ramaze/controller.rb +1 -1
- data/spec/ramaze/controller/template_resolving.rb +1 -1
- data/spec/ramaze/dispatcher/file.rb +24 -0
- data/spec/ramaze/error.rb +28 -29
- data/spec/ramaze/helper/cgi.rb +43 -0
- data/spec/ramaze/helper/pager.rb +27 -0
- data/spec/ramaze/helper/partial.rb +38 -0
- data/spec/ramaze/helper/template/partial.xhtml +1 -0
- data/spec/ramaze/inform/informer.rb +1 -1
- data/spec/ramaze/localize.rb +1 -1
- data/spec/ramaze/morpher.rb +3 -3
- data/spec/ramaze/request.rb +1 -3
- data/spec/ramaze/template.rb +9 -7
- data/spec/ramaze/template/haml.rb +2 -1
- metadata +21 -7
- data/examples/todolist/public/404.jpg +0 -0
- data/examples/todolist/public/error.xhtml +0 -74
- data/lib/ramaze/controller/render.rb +0 -90
@@ -0,0 +1,31 @@
|
|
1
|
+
# Copyright (c) 2006 Michael Fellinger m.fellinger@gmail.com
|
2
|
+
# All files in this distribution are subject to the terms of the Ruby license.
|
3
|
+
|
4
|
+
require 'ramaze'
|
5
|
+
|
6
|
+
# you can access it now with http://localhost:7000/
|
7
|
+
# This should output
|
8
|
+
# Hello, World!
|
9
|
+
# in your browser
|
10
|
+
|
11
|
+
class MainController < Ramaze::Controller
|
12
|
+
def index
|
13
|
+
"Hello, World!"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def check
|
18
|
+
os = []
|
19
|
+
ObjectSpace.each_object{|o| os << o }
|
20
|
+
p os.inject(Hash.new(0)){|s,v| s[v.class] += 1; s}.sort_by{|k,v| v}
|
21
|
+
end
|
22
|
+
|
23
|
+
Thread.new do
|
24
|
+
loop do
|
25
|
+
check
|
26
|
+
sleep 5
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
Ramaze::Inform.loggers.clear
|
31
|
+
Ramaze.start :adapter => :mongrel, :sourcereload => false
|
@@ -1,14 +1,19 @@
|
|
1
1
|
# Copyright (c) 2006 Michael Fellinger m.fellinger@gmail.com
|
2
2
|
# All files in this distribution are subject to the terms of the Ruby license.
|
3
3
|
|
4
|
-
|
4
|
+
# Default url mappings are:
|
5
|
+
# a controller called Main is mapped on the root of the site: /
|
6
|
+
# a controller called Something is mapped on: /something
|
7
|
+
# If you want to override this, add a line like this inside the class
|
8
|
+
# map '/otherurl'
|
9
|
+
# this will force the controller to be mounted on: /otherurl
|
5
10
|
|
6
|
-
|
11
|
+
class MainController < Controller
|
7
12
|
|
8
13
|
def index
|
9
14
|
@tasks = []
|
10
|
-
TodoList.original.each do |title,
|
11
|
-
if
|
15
|
+
TodoList.original.each do |title, value|
|
16
|
+
if value[:done]
|
12
17
|
status = 'done'
|
13
18
|
toggle = A('Open Task', :href => Rs(:open, title))
|
14
19
|
else
|
@@ -25,7 +30,7 @@ class MainController < Controller
|
|
25
30
|
if title = request['title']
|
26
31
|
title.strip!
|
27
32
|
if title.empty?
|
28
|
-
|
33
|
+
failed("Please enter a title")
|
29
34
|
redirect '/new'
|
30
35
|
end
|
31
36
|
TodoList[title] = {:done => false}
|
@@ -44,22 +49,18 @@ class MainController < Controller
|
|
44
49
|
TodoList.delete title
|
45
50
|
end
|
46
51
|
|
47
|
-
|
48
|
-
|
49
|
-
def redirect_index
|
50
|
-
redirect(Rs())
|
51
|
-
end
|
52
|
+
helper :aspect
|
53
|
+
after(:create, :open, :close, :delete){ redirect(Rs()) }
|
52
54
|
|
53
55
|
private
|
54
56
|
|
55
|
-
def
|
57
|
+
def failed(message)
|
56
58
|
flash[:error] = message
|
57
59
|
end
|
58
60
|
|
59
61
|
def task_status title, status
|
60
|
-
p title
|
61
62
|
unless task = TodoList[title]
|
62
|
-
|
63
|
+
failed "No such Task: `#{title}'"
|
63
64
|
redirect_referer
|
64
65
|
end
|
65
66
|
|
data/examples/whywiki/main.rb
CHANGED
@@ -16,7 +16,7 @@ class WikiController < Controller
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def show page = 'Home'
|
19
|
-
@page = page
|
19
|
+
@page = CGI.unescape(page)
|
20
20
|
@text = Db[page].to_s
|
21
21
|
|
22
22
|
@text.gsub!(/\[\[(.*?)\]\]/) do |m|
|
@@ -28,7 +28,7 @@ class WikiController < Controller
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def edit page = 'Home'
|
31
|
-
@page = page
|
31
|
+
@page = CGI.unescape(page)
|
32
32
|
@text = Db[page]
|
33
33
|
end
|
34
34
|
|
@@ -6,14 +6,14 @@
|
|
6
6
|
a.nonexists{ color: #f00; }
|
7
7
|
</style>
|
8
8
|
</head>
|
9
|
-
#{
|
9
|
+
#{ A("< Home", :href => R(self)) unless @page == "Home" }
|
10
10
|
<body>
|
11
11
|
<h1>#{@page}</h1>
|
12
12
|
<?r if @text.empty? ?>
|
13
|
-
#{
|
13
|
+
#{ A("Create #{@page}?",:href => R(self, :edit, CGI.escape(@page))) }
|
14
14
|
<?r else ?>
|
15
15
|
<div>
|
16
|
-
#{
|
16
|
+
#{ A("Edit #{@page}?", :href => R(self, :edit, CGI.escape(@page))) }
|
17
17
|
#{@text}
|
18
18
|
</div>
|
19
19
|
<?r end ?>
|
@@ -1,8 +1,25 @@
|
|
1
1
|
# Copyright (c) 2006 Michael Fellinger m.fellinger@gmail.com
|
2
2
|
# All files in this distribution are subject to the terms of the Ruby license.
|
3
3
|
|
4
|
+
# Default url mappings are:
|
5
|
+
# a controller called Main is mapped on the root of the site: /
|
6
|
+
# a controller called Something is mapped on: /something
|
7
|
+
# If you want to override this, add a line like this inside the class
|
8
|
+
# map '/otherurl'
|
9
|
+
# this will force the controller to be mounted on: /otherurl
|
10
|
+
|
4
11
|
class MainController < Controller
|
12
|
+
|
13
|
+
# the index action is called automatically when no other action is specified
|
5
14
|
def index
|
6
|
-
"
|
15
|
+
@welcome = "Welcome to Ramaze!"
|
7
16
|
end
|
17
|
+
|
18
|
+
# the string returned at the end of the function is used as the html body
|
19
|
+
# if there is no template for the action. if there is a template, the string
|
20
|
+
# is silently ignored
|
21
|
+
def notemplate
|
22
|
+
"there is no template associated with this action"
|
23
|
+
end
|
24
|
+
|
8
25
|
end
|
@@ -1,6 +1,15 @@
|
|
1
1
|
<Page>
|
2
|
-
<h1
|
2
|
+
<h1>#{@welcome}</h1>
|
3
|
+
<p>Ramaze is working correctly with this application, now you can start working</p
|
4
|
+
|
3
5
|
<p>
|
4
|
-
|
6
|
+
To start you can modify:
|
7
|
+
<ol>
|
8
|
+
<li><code>template/index.xhtml</code>, which this text</li>
|
9
|
+
<li><code>src/elements/page.rb</code>, which is the Element around this text</li>
|
10
|
+
<li><code>src/controllers/main.rb</code>, where you can change the header of this page and the <a href="/notemplate">notemplate</a> action</li>
|
11
|
+
<li><code>src/model.rb</code>, which is the the persistent backend for your app</li>
|
12
|
+
</ol>
|
5
13
|
</p>
|
14
|
+
<p>You can also read the tutorial in the <code>doc/</code> directory of ramaze or browse the <a href="http://ramaze.rubyforge.org/rdoc/files/doc/README.html">rdocs</a><p>
|
6
15
|
</Page>
|
data/lib/ramaze.rb
CHANGED
data/lib/ramaze/action.rb
CHANGED
@@ -5,17 +5,116 @@ module Ramaze
|
|
5
5
|
|
6
6
|
unless defined?(Action) # prevent problems for SourceReload
|
7
7
|
|
8
|
+
members = %w[method params template controller path binding engine instance]
|
9
|
+
|
8
10
|
# The Action holds information that is essential to render the action for a
|
9
11
|
# request.
|
10
12
|
|
11
|
-
class Action < Struct.new('Action',
|
12
|
-
|
13
|
-
|
13
|
+
class Action < Struct.new('Action', *members)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
require 'ramaze/action/render'
|
18
|
+
|
19
|
+
class Action
|
20
|
+
class << self
|
21
|
+
|
22
|
+
# Instantiate with given Hash, takes both string/symbol keys.
|
23
|
+
# Only keys that match members of the Action-Struct are used.
|
24
|
+
|
25
|
+
def create(hash = {})
|
26
|
+
i = new
|
27
|
+
members.each do |key|
|
28
|
+
i.send("#{key}=", (hash[key] || hash[key.to_sym]))
|
29
|
+
end
|
30
|
+
i
|
14
31
|
end
|
15
32
|
|
16
|
-
|
17
|
-
|
33
|
+
# Thread.current[:action] returns the instance of Action you are currently in.
|
34
|
+
|
35
|
+
def current
|
36
|
+
Thread.current[:action]
|
18
37
|
end
|
19
38
|
end
|
39
|
+
|
40
|
+
# nicer representation of the Action
|
41
|
+
|
42
|
+
def to_s
|
43
|
+
m, p, t = method.inspect, params.inspect, template.inspect
|
44
|
+
%{#<Action method=#{m}, params=#{p} template=#{t}>}
|
45
|
+
end
|
46
|
+
|
47
|
+
# Set the method, will be converted to a string and set to nil if empty.
|
48
|
+
|
49
|
+
def method=(meth)
|
50
|
+
meth = meth.to_s
|
51
|
+
self[:method] = (meth.empty? ? nil : meth)
|
52
|
+
end
|
53
|
+
|
54
|
+
# runs all parameters assigned through flatten and CGI::unescape
|
55
|
+
|
56
|
+
def params=(*par)
|
57
|
+
self[:params] = par.flatten.compact.map{|pa| CGI.unescape(pa.to_s)}
|
58
|
+
end
|
59
|
+
|
60
|
+
# Use this as key for caches.
|
61
|
+
|
62
|
+
def relaxed_hash
|
63
|
+
[controller, method, params, template, path].hash
|
64
|
+
end
|
65
|
+
|
66
|
+
# A Hash representation of Action
|
67
|
+
|
68
|
+
def to_hash
|
69
|
+
hash = {}
|
70
|
+
members.each{|m| hash[m.to_sym] = send(m)}
|
71
|
+
hash
|
72
|
+
end
|
73
|
+
|
74
|
+
# Determines based on controller.trait[:engine] and the template extensions
|
75
|
+
# which engine has to be used.
|
76
|
+
# Defaults to Template::Ezamar
|
77
|
+
|
78
|
+
def engine
|
79
|
+
return self[:engine] if self[:engine]
|
80
|
+
default = controller.trait.fetch(:engine, Template::Ezamar)
|
81
|
+
return default unless template
|
82
|
+
|
83
|
+
engines = Template::ENGINES
|
84
|
+
return default if engines.empty?
|
85
|
+
|
86
|
+
ext = File.extname(template).gsub(/^\./, '')
|
87
|
+
ext_engine = engines.find{|e| e.last.include?(ext)}.first
|
88
|
+
|
89
|
+
self[:engine] = (ext_engine || default)
|
90
|
+
end
|
91
|
+
|
92
|
+
# Returns an instance of controller, will be cached on first access.
|
93
|
+
|
94
|
+
def instance
|
95
|
+
self[:instance] ||= controller.new
|
96
|
+
end
|
97
|
+
|
98
|
+
# Returns a binding of the instance, will be cached on first access.
|
99
|
+
|
100
|
+
def binding
|
101
|
+
self[:binding] ||= instance.instance_eval{ binding }
|
102
|
+
end
|
103
|
+
|
104
|
+
# Hook for AspectHelper
|
105
|
+
|
106
|
+
def before_process
|
107
|
+
end
|
108
|
+
|
109
|
+
# Hook for AspectHelper
|
110
|
+
|
111
|
+
def after_process
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# Shortcut to create new instances of Action via Action::fill
|
116
|
+
|
117
|
+
def self.Action(hash = {})
|
118
|
+
Action.create(hash)
|
20
119
|
end
|
21
120
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# Copyright (c) 2006 Michael Fellinger m.fellinger@gmail.com
|
2
|
+
# All files in this distribution are subject to the terms of the Ruby license.
|
3
|
+
|
4
|
+
module Ramaze
|
5
|
+
class Action
|
6
|
+
|
7
|
+
# Render this instance of Action, this will (eventually) pass itself to
|
8
|
+
# Action#engine.transform
|
9
|
+
# Usage, given that Foo is a Controller and has the method/template
|
10
|
+
# for index:
|
11
|
+
# > Action(:controller => Foo).render
|
12
|
+
# #> 'bar'
|
13
|
+
|
14
|
+
def render
|
15
|
+
Inform.debug("The Action: #{self}")
|
16
|
+
Thread.current[:action] = self
|
17
|
+
|
18
|
+
if should_cache?
|
19
|
+
cached_render
|
20
|
+
else
|
21
|
+
uncached_render
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def cached_render
|
26
|
+
action_cache = Cache.actions
|
27
|
+
|
28
|
+
if out = action_cache[relaxed_hash]
|
29
|
+
Inform.debug("Using Cached version")
|
30
|
+
return out
|
31
|
+
end
|
32
|
+
|
33
|
+
Inform.debug("Compiling Action")
|
34
|
+
action_cache[relaxed_hash] = uncached_render
|
35
|
+
end
|
36
|
+
|
37
|
+
def uncached_render
|
38
|
+
[ before_process,
|
39
|
+
engine.transform(self),
|
40
|
+
after_process,
|
41
|
+
].join
|
42
|
+
end
|
43
|
+
|
44
|
+
def should_cache?
|
45
|
+
ctrait = controller.trait
|
46
|
+
actions_cached = ctrait[:actions_cached]
|
47
|
+
|
48
|
+
[ Global.cache_all,
|
49
|
+
ctrait[:cache_all],
|
50
|
+
actions_cached.map{|k| k.to_s}.include?(method),
|
51
|
+
].any?
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/ramaze/adapter.rb
CHANGED
@@ -1,11 +1,20 @@
|
|
1
1
|
# Copyright (c) 2006 Michael Fellinger m.fellinger@gmail.com
|
2
2
|
# All files in this distribution are subject to the terms of the Ruby license.
|
3
3
|
|
4
|
-
require 'ramaze/adapter'
|
5
|
-
require 'mongrel'
|
6
|
-
require 'rack/handler/mongrel'
|
7
|
-
|
8
4
|
module Ramaze
|
5
|
+
if ENV['SWIFT']
|
6
|
+
require 'swiftcore/swiftiplied_mongrel'
|
7
|
+
Inform.debug "Using Swiftiplied Mongrel"
|
8
|
+
elsif ENV['EVENT']
|
9
|
+
require 'swiftcore/evented_mongrel'
|
10
|
+
Inform.debug "Using Evented Mongrel"
|
11
|
+
else
|
12
|
+
require 'mongrel'
|
13
|
+
end
|
14
|
+
|
15
|
+
require 'ramaze/adapter'
|
16
|
+
require 'rack/handler/mongrel'
|
17
|
+
|
9
18
|
module Adapter
|
10
19
|
class Mongrel < Base
|
11
20
|
class << self
|
data/lib/ramaze/cache.rb
CHANGED
@@ -12,18 +12,27 @@ module Ramaze
|
|
12
12
|
|
13
13
|
class Cache
|
14
14
|
include Enumerable
|
15
|
-
CACHES = {}
|
15
|
+
CACHES = {} unless defined?(CACHES)
|
16
16
|
|
17
|
-
|
18
|
-
# sinleton-methods on Cache
|
17
|
+
class << self
|
19
18
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
19
|
+
def startup(options)
|
20
|
+
Cache.add :compiled, :actions, :patterns, :resolved, :shield
|
21
|
+
end
|
22
|
+
|
23
|
+
# This will define a method to access a new cache directly over
|
24
|
+
# sinleton-methods on Cache
|
25
|
+
|
26
|
+
def add *keys
|
27
|
+
keys.each do |key|
|
28
|
+
CACHES[key] = new
|
29
|
+
self.class.class_eval do
|
30
|
+
define_method(key){ CACHES[key] }
|
31
|
+
end
|
25
32
|
end
|
33
|
+
Inform.debug("Added caches for: #{keys.join(', ')}")
|
26
34
|
end
|
35
|
+
|
27
36
|
end
|
28
37
|
|
29
38
|
def initialize(cache = Global.cache)
|