nitro 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
|