nitro 0.11.0 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +150 -0
- data/README +1 -1
- data/RELEASES +89 -0
- data/Rakefile +3 -3
- data/{AUTHORS → doc/AUTHORS} +0 -0
- data/{LICENSE → doc/LICENSE} +0 -0
- data/doc/bugs.txt +2 -1
- data/examples/README.windows +2 -2
- data/examples/blog/lib/blog/controller.rb +9 -8
- data/examples/blog/log/apache.error_log +71 -0
- data/{lib/xsl → examples/blog/root}/base.xsl +0 -0
- data/examples/blog/root/error.xhtml +56 -0
- data/examples/blog/root/index.xhtml +2 -2
- data/examples/blog/root/recent_posts.xhtml +1 -1
- data/examples/blog/root/style.xsl +4 -4
- data/examples/blog/run.rb +1 -2
- data/examples/no_xsl_blog/root/index.xhtml +2 -2
- data/examples/no_xsl_blog/root/recent_posts.xhtml +1 -1
- data/examples/why_wiki/run.rb +19 -19
- data/lib/nitro.rb +2 -21
- data/lib/nitro/adapters/webrick.rb +19 -3
- data/lib/nitro/context.rb +15 -1
- data/lib/nitro/controller.rb +84 -49
- data/lib/nitro/dispatcher.rb +30 -6
- data/lib/nitro/markup.rb +4 -2
- data/lib/nitro/render.rb +15 -11
- data/lib/nitro/routing.rb +33 -0
- data/lib/nitro/runner.rb +38 -3
- data/lib/nitro/scaffold.rb +7 -4
- data/lib/nitro/shaders.rb +11 -4
- data/lib/nitro/template.rb +140 -0
- data/lib/og.rb +25 -11
- data/lib/og/adapter.rb +141 -7
- data/lib/og/adapters/mysql.rb +41 -3
- data/lib/og/adapters/oracle.rb +4 -3
- data/lib/og/adapters/psql.rb +3 -3
- data/lib/og/adapters/sqlite.rb +3 -3
- data/lib/og/connection.rb +5 -1
- data/lib/og/database.rb +26 -12
- data/lib/og/enchant.rb +50 -16
- data/lib/og/meta.rb +15 -15
- data/lib/og/observer.rb +53 -0
- data/test/glue/tc_property_type_checking.rb +3 -0
- data/test/nitro/tc_controller.rb +1 -1
- data/test/nitro/tc_dispatcher.rb +1 -1
- data/test/nitro/tc_template.rb +32 -0
- data/test/og/tc_many_to_many.rb +62 -0
- data/test/og/tc_observer.rb +85 -0
- data/test/tc_og.rb +16 -2
- metadata +12 -14
- data/bin/cluster +0 -218
- data/examples/why_wiki/wiki.yml +0 -6
- data/examples/wiki.yml +0 -1
- data/lib/nitro/ui/select.rb +0 -40
- data/lib/nitro/ui/sitemap.rb +0 -183
- data/test/nitro/ui/tc_sitemap.rb +0 -37
@@ -13,8 +13,8 @@
|
|
13
13
|
<h3 class="title">#{entry.title}</h3>
|
14
14
|
#{entry.body}
|
15
15
|
<div class="footer">
|
16
|
-
posted by #{entry.author} at <a href="
|
17
|
-
<a href="
|
16
|
+
posted by #{entry.author} at <a href="#{entry.view_uri}">#{entry.create_time.strftime('%R %p')}</a> |
|
17
|
+
<a href="#{entry.view_uri}#comments">#{entry.comments_count} comments</a>.
|
18
18
|
<?r if session[:owner] ?>
|
19
19
|
[<a href="del_entry?oid=#{entry.oid}">del</a>]
|
20
20
|
<?r end ?>
|
@@ -5,7 +5,7 @@ A Simple Shader
|
|
5
5
|
|
6
6
|
* George Moschovitis <gm@navel.gr>
|
7
7
|
(c) 2004-2005 Navel, all rights reserved.
|
8
|
-
$Id: style.xsl
|
8
|
+
$Id: style.xsl 270 2005-03-07 17:52:16Z gmosx $
|
9
9
|
-->
|
10
10
|
|
11
11
|
<!DOCTYPE shader
|
@@ -23,13 +23,13 @@ $Id: style.xsl 259 2005-02-15 08:54:54Z gmosx $
|
|
23
23
|
xmlns:x="http://www.navel.gr/xml/shader.xsd" version="1.0"
|
24
24
|
exclude-result-prefixes="x xl">
|
25
25
|
|
26
|
-
<xsl:include href="
|
26
|
+
<xsl:include href="root/base.xsl" />
|
27
27
|
|
28
28
|
<xsl:output method="xml" indent="yes" encoding="iso-8859-1" />
|
29
29
|
|
30
30
|
<xsl:template name="x:head">
|
31
31
|
<head>
|
32
|
-
<title>#
|
32
|
+
<title>#(@context.conf.name)</title>
|
33
33
|
<meta name="title" content="Blog" />
|
34
34
|
<meta name="description" content="Example" />
|
35
35
|
<meta name="keywords" content="nitro, example, blog" />
|
@@ -39,7 +39,7 @@ $Id: style.xsl 259 2005-02-15 08:54:54Z gmosx $
|
|
39
39
|
|
40
40
|
<xsl:apply-templates select="x:block[@id='meta']"/>
|
41
41
|
|
42
|
-
<base href="#
|
42
|
+
<base href="#(@context.host_url)/" />
|
43
43
|
<link href="/style.css" rel="stylesheet" type="text/css" media="screen" />
|
44
44
|
<link rel="alternate" type="application/rss+xml" title="Latest Entries" href="#{@context.host_url}/xml/list_entry" />
|
45
45
|
<link rel="alternate" type="application/rss+xml" title="Latest Comments" href="#{@context.host_url}/xml/list_comment" />
|
data/examples/blog/run.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# * George Moschovitis <gm@navel.gr>
|
2
2
|
# (c) 2004-2005 Navel, all rights reserved.
|
3
|
-
# $Id: run.rb
|
3
|
+
# $Id: run.rb 270 2005-03-07 17:52:16Z gmosx $
|
4
4
|
|
5
5
|
# $:.unshift '/home/gmosx/navel/nitro/lib'
|
6
6
|
|
@@ -11,7 +11,6 @@ require 'og'
|
|
11
11
|
|
12
12
|
require 'lib/blog'
|
13
13
|
|
14
|
-
# Nitro.resolve_action_arguments = true
|
15
14
|
# Og.create_schema = false
|
16
15
|
# Session.store_type = :drb
|
17
16
|
|
@@ -12,8 +12,8 @@
|
|
12
12
|
<h3 class="title">#{entry.title}</h3>
|
13
13
|
#{entry.body}
|
14
14
|
<div class="footer">
|
15
|
-
posted by #{entry.author} at <a href="
|
16
|
-
<a href="
|
15
|
+
posted by #{entry.author} at <a href="#{entry.view_uri}">#{entry.create_time.strftime('%R %p')}</a> |
|
16
|
+
<a href="#{entry.view_uri}#comments">#{entry.comments_count} comments</a>.
|
17
17
|
<?r if session[:owner] ?>
|
18
18
|
[<a href="del_entry?oid=#{entry.oid}">del</a>]
|
19
19
|
<?r end ?>
|
data/examples/why_wiki/run.rb
CHANGED
@@ -1,57 +1,57 @@
|
|
1
1
|
# * George Moschovitis <gm@navel.gr>
|
2
|
-
# $Id: run.rb
|
2
|
+
# $Id: run.rb 270 2005-03-07 17:52:16Z gmosx $
|
3
3
|
|
4
4
|
require 'cgi'
|
5
5
|
require 'redcloth'
|
6
6
|
require 'yaml/store'
|
7
7
|
|
8
8
|
require 'nitro'; include N
|
9
|
+
require 'nitro/adapters/webrick'
|
9
10
|
|
10
11
|
# A simple wiki. A straight conversion of the redhanded.hobix.com
|
11
12
|
# example. Original code by why the lucky stiff.
|
12
13
|
# This is just a cool example, not the preffered way to write
|
13
14
|
# Nitro applications.
|
14
15
|
|
16
|
+
WIKI = YAML::Store.new('wiki.yml')
|
17
|
+
|
15
18
|
class Wiki < Component
|
16
|
-
HP = 'HomePage'
|
17
|
-
WIKI = YAML::Store.new('wiki.yml')
|
18
19
|
|
19
20
|
def index
|
20
|
-
|
21
|
+
@p = 'Home'
|
21
22
|
show
|
22
23
|
end
|
23
24
|
|
24
25
|
def show
|
25
|
-
p
|
26
|
-
o.
|
27
|
-
o.a(HP, :href => '/') unless p == HP
|
26
|
+
o.h1(@p)
|
27
|
+
o.a('Home', :href => '/') unless @p == 'Home'
|
28
28
|
WIKI.transaction do
|
29
|
-
if WIKI[p]
|
30
|
-
o << RedCloth.new(WIKI[p]).to_html.gsub(/([A-Z]\w+){2}/) { "<a href='show
|
31
|
-
o.a 'Edit', :href => "edit
|
29
|
+
if WIKI[@p]
|
30
|
+
o << RedCloth.new(WIKI[@p]).to_html.gsub(/([A-Z]\w+){2}/) { "<a href='/show/#$&'>#$&</a>" }
|
31
|
+
o.a 'Edit', :href => "/edit/#@p"
|
32
32
|
else
|
33
|
-
o.p("No page #{p}. ").a('Create?', :href => "edit
|
33
|
+
o.p("No page #{p}. ").a('Create?', :href => "/edit/#@p")
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
37
|
+
action :show, :route => /show\/(.*)/, 'p' => String
|
37
38
|
|
38
39
|
def edit
|
39
|
-
p = request['p'].to_s
|
40
40
|
if c = request['c']
|
41
|
-
WIKI.transaction { WIKI[p] = c
|
42
|
-
redirect "show
|
41
|
+
WIKI.transaction { WIKI[@p] = c }
|
42
|
+
redirect "/show/#@p"
|
43
43
|
end
|
44
44
|
WIKI.transaction do
|
45
|
-
o.h1 "Editing
|
46
|
-
o.a('Show', :href => "show
|
45
|
+
o.h1 "Editing #@p"
|
46
|
+
o.a('Show', :href => "/show/#@p").br.br
|
47
47
|
o.form(:method => 'post') {
|
48
|
-
o.input :type => 'hidden', :name => 'p', :value => p
|
49
|
-
o.textarea WIKI[p].to_s, :name => 'c', :style => 'width: 90%; height: 200px'
|
48
|
+
o.input :type => 'hidden', :name => 'p', :value => @p
|
49
|
+
o.textarea WIKI[@p].to_s, :name => 'c', :style => 'width: 90%; height: 200px'
|
50
50
|
o.br.br.submit
|
51
51
|
}
|
52
52
|
end
|
53
53
|
end
|
54
|
+
action :edit, :route => /edit\/(.*)/, 'p' => String
|
54
55
|
end
|
55
56
|
|
56
|
-
require 'nitro/adapters/webrick'
|
57
57
|
Webrick.start(:dispatcher => Dispatcher.new(Wiki))
|
data/lib/nitro.rb
CHANGED
@@ -12,7 +12,7 @@
|
|
12
12
|
#
|
13
13
|
# * George Moschovitis <gm@navel.gr>
|
14
14
|
# (c) 2004-2005 Navel, all rights reserved.
|
15
|
-
# $Id: nitro.rb
|
15
|
+
# $Id: nitro.rb 270 2005-03-07 17:52:16Z gmosx $
|
16
16
|
|
17
17
|
require 'glue'
|
18
18
|
require 'glue/logger'
|
@@ -27,31 +27,12 @@ module Nitro
|
|
27
27
|
|
28
28
|
# The version.
|
29
29
|
|
30
|
-
Version = '0.
|
30
|
+
Version = '0.12.0'
|
31
31
|
|
32
32
|
# Library path.
|
33
33
|
|
34
34
|
LibPath = File.dirname(__FILE__)
|
35
35
|
|
36
|
-
# If set to true, action methods can have arguments which are
|
37
|
-
# automatically resolved.
|
38
|
-
#
|
39
|
-
# === Example
|
40
|
-
#
|
41
|
-
# def list(username, oid)
|
42
|
-
# ...
|
43
|
-
# end
|
44
|
-
#
|
45
|
-
# http://www.mysite.com/list?username=tml;oid=2
|
46
|
-
#
|
47
|
-
# calls list() with the correct parameters, no need to
|
48
|
-
# use request['oid'], just use oid.
|
49
|
-
#
|
50
|
-
# WARNING: this feature requires the ParseTree library which
|
51
|
-
# is not compatible with Windows.
|
52
|
-
|
53
|
-
mattr_accessor :resolve_action_arguments, false
|
54
|
-
|
55
36
|
end
|
56
37
|
|
57
38
|
# gmosx: leave them here.
|
@@ -10,6 +10,10 @@ require 'nitro/context'
|
|
10
10
|
require 'nitro/dispatcher'
|
11
11
|
|
12
12
|
module WEBrick
|
13
|
+
|
14
|
+
class HTTPRequest
|
15
|
+
attr :socket
|
16
|
+
end
|
13
17
|
|
14
18
|
class HTTPResponse
|
15
19
|
def header=(header)
|
@@ -103,13 +107,25 @@ class WebrickAdapter < WEBrick::HTTPServlet::AbstractServlet
|
|
103
107
|
|
104
108
|
context = Context.new(@conf)
|
105
109
|
|
106
|
-
context.params = req.query
|
107
110
|
context.headers = {}
|
108
111
|
req.header.each { |h, v| context.headers[h.upcase] = v.first }
|
109
112
|
context.headers.update(req.meta_vars)
|
110
|
-
context.cookies = {}
|
111
|
-
req.cookies.each { |c| context.cookies[c.name] = c.value }
|
112
113
|
|
114
|
+
context.params = {}
|
115
|
+
req.query.each do |k, v|
|
116
|
+
if k =~ /(.*)\[\]$/
|
117
|
+
context.params[k] = v
|
118
|
+
else
|
119
|
+
context.params[k] = v.to_s
|
120
|
+
end
|
121
|
+
end
|
122
|
+
# context.in = req.socket
|
123
|
+
# CgiUtils.parse_params(context)
|
124
|
+
|
125
|
+
#context.cookies = {}
|
126
|
+
#req.cookies.each { |c| context.cookies[c.name] = c.value }
|
127
|
+
CgiUtils.parse_cookies(context)
|
128
|
+
|
113
129
|
context.render(path)
|
114
130
|
|
115
131
|
res.status = context.status
|
data/lib/nitro/context.rb
CHANGED
@@ -56,7 +56,21 @@ class Context
|
|
56
56
|
@session.sync if @session
|
57
57
|
end
|
58
58
|
alias_method :finish, :close
|
59
|
-
|
59
|
+
|
60
|
+
#--
|
61
|
+
# FIXME: something more elegant/efficient.
|
62
|
+
#++
|
63
|
+
|
64
|
+
def out
|
65
|
+
if @out == '(error)'
|
66
|
+
@out = ''
|
67
|
+
render '/error'
|
68
|
+
@out
|
69
|
+
else
|
70
|
+
@out
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
60
74
|
# Lazy lookup of the session to avoid costly cookie
|
61
75
|
# lookup when not needed.
|
62
76
|
|
data/lib/nitro/controller.rb
CHANGED
@@ -7,7 +7,70 @@ require 'nitro/scaffold'
|
|
7
7
|
require 'nitro/filters'
|
8
8
|
|
9
9
|
module N
|
10
|
+
|
11
|
+
# Encapsulates metadata that describe an action
|
12
|
+
# parameter.
|
13
|
+
#
|
14
|
+
# [+default+]
|
15
|
+
# The default value.
|
16
|
+
#
|
17
|
+
# [+format+]
|
18
|
+
# The expected format.
|
19
|
+
#
|
20
|
+
# [+required+]
|
21
|
+
# Is this parameter required?
|
22
|
+
|
23
|
+
ActionParam = Struct.new(:default, :format, :required)
|
24
|
+
|
25
|
+
# Encapsulates metadata that describe an action.
|
26
|
+
|
27
|
+
class ActionMeta < Hash
|
28
|
+
|
29
|
+
# The arguments of the given method.
|
30
|
+
|
31
|
+
attr_accessor :params
|
32
|
+
|
33
|
+
# Initialize the metadata.
|
34
|
+
|
35
|
+
def initialize(options)
|
36
|
+
@params = {}
|
37
|
+
update(options)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Update the metadata.
|
41
|
+
#
|
42
|
+
# [+options+]
|
43
|
+
# A hash containing the metadata. Options with Symbol
|
44
|
+
# keys are considered metadata, options with
|
45
|
+
# String keys are the named parameters for the action.
|
10
46
|
|
47
|
+
def update(options)
|
48
|
+
options.each do |k, v|
|
49
|
+
case k
|
50
|
+
when String
|
51
|
+
# A key of type String denotes a parameter.
|
52
|
+
case v
|
53
|
+
when Regexp
|
54
|
+
@params[k] = ActionParam.new(nil, v, nil)
|
55
|
+
when ActionParam
|
56
|
+
@params[k] = v
|
57
|
+
else
|
58
|
+
if v == :required
|
59
|
+
@params[k] = ActionParam.new(nil, nil, true)
|
60
|
+
else
|
61
|
+
@params[k] = ActionParam.new(v, nil, nil)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
when Symbol
|
65
|
+
self[k] = v
|
66
|
+
else
|
67
|
+
raise TypeError.new('The keys must be either Symbols or Strings.')
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
11
74
|
# The Controller part in the MVC paradigm.
|
12
75
|
# A Controller encpsulates a set of actions.
|
13
76
|
|
@@ -16,6 +79,11 @@ class Controller
|
|
16
79
|
include Scaffolding
|
17
80
|
include Filtering
|
18
81
|
|
82
|
+
# A hash containing metadata for the action
|
83
|
+
# methods.
|
84
|
+
|
85
|
+
cattr_accessor :action_metadata, {}
|
86
|
+
|
19
87
|
# Use the method_missing hook to compile the actions
|
20
88
|
# for this controller.
|
21
89
|
|
@@ -28,6 +96,7 @@ class Controller
|
|
28
96
|
end
|
29
97
|
|
30
98
|
class << self
|
99
|
+
|
31
100
|
alias __old_inherited inherited
|
32
101
|
|
33
102
|
def inherited(subclass)
|
@@ -37,70 +106,36 @@ class Controller
|
|
37
106
|
__old_inherited(subclass)
|
38
107
|
end
|
39
108
|
|
109
|
+
# Define metadata for an action. This is a helper
|
110
|
+
# macro.
|
111
|
+
|
112
|
+
def action(name, options)
|
113
|
+
if meta = @@action_metadata[name]
|
114
|
+
meta.update(options)
|
115
|
+
else
|
116
|
+
@@action_metadata[name] = ActionMeta.new(options)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
40
120
|
# Return the 'action' methods for this Controller.
|
41
121
|
# Some dangerous methods from ancestors are removed.
|
42
122
|
|
43
123
|
def action_methods
|
44
124
|
classes = self.ancestors.reject do |a|
|
45
|
-
[Object, Kernel, Render].include?(a)
|
125
|
+
[Object, Kernel, Render, Controller].include?(a)
|
46
126
|
end
|
127
|
+
|
128
|
+
classes.delete(PP::ObjectMixin) if defined?(PP::ObjectMixin)
|
47
129
|
|
48
130
|
methods = classes.inject([]) do |action_methods, klass|
|
49
131
|
action_methods + klass.public_instance_methods(false)
|
50
132
|
end
|
51
133
|
|
52
|
-
methods.delete('method_missing')
|
53
|
-
|
54
|
-
# temp hack, FIXME:
|
55
|
-
|
56
|
-
methods.delete('pretty_print')
|
57
|
-
methods.delete('pretty_print_cycle')
|
58
|
-
methods.delete('pretty_print_instance_variables')
|
59
|
-
methods.delete('pretty_print_inspect')
|
134
|
+
# methods.delete('method_missing')
|
60
135
|
|
61
136
|
return methods
|
62
137
|
end
|
63
138
|
|
64
|
-
# Return the arguments of the given action.
|
65
|
-
|
66
|
-
def action_method_arguments(action)
|
67
|
-
if Nitro.resolve_action_arguments
|
68
|
-
unless defined?(ArgsProcessor)
|
69
|
-
begin
|
70
|
-
require_gem 'ParseTree'
|
71
|
-
require 'parse_tree'
|
72
|
-
require 'sexp_processor'
|
73
|
-
rescue
|
74
|
-
# No parse tree support
|
75
|
-
end
|
76
|
-
|
77
|
-
Object.class_eval %{
|
78
|
-
class ArgsProcessor < SexpProcessor # :nodoc:
|
79
|
-
attr_accessor :args
|
80
|
-
|
81
|
-
def initialize
|
82
|
-
super
|
83
|
-
@require_empty = false
|
84
|
-
end
|
85
|
-
|
86
|
-
def process_args(exp)
|
87
|
-
@args = exp.slice(1..-1)
|
88
|
-
return Sexp.new(exp)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
}
|
92
|
-
end
|
93
|
-
|
94
|
-
ptree = ParseTree.new
|
95
|
-
sexpp = ArgsProcessor.new
|
96
|
-
sexp = ptree.parse_tree_for_method(self, action)
|
97
|
-
sexpp.process(sexp)
|
98
|
-
|
99
|
-
return sexpp.args
|
100
|
-
else
|
101
|
-
return []
|
102
|
-
end
|
103
|
-
end
|
104
139
|
end
|
105
140
|
end
|
106
141
|
|