nitro 0.11.0 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/ChangeLog +150 -0
  2. data/README +1 -1
  3. data/RELEASES +89 -0
  4. data/Rakefile +3 -3
  5. data/{AUTHORS → doc/AUTHORS} +0 -0
  6. data/{LICENSE → doc/LICENSE} +0 -0
  7. data/doc/bugs.txt +2 -1
  8. data/examples/README.windows +2 -2
  9. data/examples/blog/lib/blog/controller.rb +9 -8
  10. data/examples/blog/log/apache.error_log +71 -0
  11. data/{lib/xsl → examples/blog/root}/base.xsl +0 -0
  12. data/examples/blog/root/error.xhtml +56 -0
  13. data/examples/blog/root/index.xhtml +2 -2
  14. data/examples/blog/root/recent_posts.xhtml +1 -1
  15. data/examples/blog/root/style.xsl +4 -4
  16. data/examples/blog/run.rb +1 -2
  17. data/examples/no_xsl_blog/root/index.xhtml +2 -2
  18. data/examples/no_xsl_blog/root/recent_posts.xhtml +1 -1
  19. data/examples/why_wiki/run.rb +19 -19
  20. data/lib/nitro.rb +2 -21
  21. data/lib/nitro/adapters/webrick.rb +19 -3
  22. data/lib/nitro/context.rb +15 -1
  23. data/lib/nitro/controller.rb +84 -49
  24. data/lib/nitro/dispatcher.rb +30 -6
  25. data/lib/nitro/markup.rb +4 -2
  26. data/lib/nitro/render.rb +15 -11
  27. data/lib/nitro/routing.rb +33 -0
  28. data/lib/nitro/runner.rb +38 -3
  29. data/lib/nitro/scaffold.rb +7 -4
  30. data/lib/nitro/shaders.rb +11 -4
  31. data/lib/nitro/template.rb +140 -0
  32. data/lib/og.rb +25 -11
  33. data/lib/og/adapter.rb +141 -7
  34. data/lib/og/adapters/mysql.rb +41 -3
  35. data/lib/og/adapters/oracle.rb +4 -3
  36. data/lib/og/adapters/psql.rb +3 -3
  37. data/lib/og/adapters/sqlite.rb +3 -3
  38. data/lib/og/connection.rb +5 -1
  39. data/lib/og/database.rb +26 -12
  40. data/lib/og/enchant.rb +50 -16
  41. data/lib/og/meta.rb +15 -15
  42. data/lib/og/observer.rb +53 -0
  43. data/test/glue/tc_property_type_checking.rb +3 -0
  44. data/test/nitro/tc_controller.rb +1 -1
  45. data/test/nitro/tc_dispatcher.rb +1 -1
  46. data/test/nitro/tc_template.rb +32 -0
  47. data/test/og/tc_many_to_many.rb +62 -0
  48. data/test/og/tc_observer.rb +85 -0
  49. data/test/tc_og.rb +16 -2
  50. metadata +12 -14
  51. data/bin/cluster +0 -218
  52. data/examples/why_wiki/wiki.yml +0 -6
  53. data/examples/wiki.yml +0 -1
  54. data/lib/nitro/ui/select.rb +0 -40
  55. data/lib/nitro/ui/sitemap.rb +0 -183
  56. 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="view_entry?oid=#{entry.oid}">#{entry.create_time.strftime('%R %p')}</a> |
17
- <a href="view_entry?oid=#{entry.oid}#comments">#{entry.comments_count} comments</a>.
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 @@
5
5
  <?r if @entries ?>
6
6
  <ul>
7
7
  <?r for entry in @entries ?>
8
- <li><a href="view_entry?oid=#{entry.oid}">#{entry.title}</a></li>
8
+ <li><a href="#{entry.view_uri}">#{entry.title}</a></li>
9
9
  <?r end ?>
10
10
  </ul>
11
11
  <?r else ?>
@@ -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 259 2005-02-15 08:54:54Z gmosx $
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="../../lib/xsl/base.xsl" />
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>#{@context.conf.name}</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="#{@context.host_url}/" />
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 266 2005-02-28 14:50:48Z gmosx $
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="view_entry?oid=#{entry.oid}">#{entry.create_time.strftime('%R %p')}</a> |
16
- <a href="view_entry?oid=#{entry.oid}#comments">#{entry.comments_count} comments</a>.
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 ?>
@@ -5,7 +5,7 @@
5
5
  <?r if @entries ?>
6
6
  <ul>
7
7
  <?r for entry in @entries ?>
8
- <li><a href="view_entry?oid=#{entry.oid}">#{entry.title}</a></li>
8
+ <li><a href="#{entry.view_uri}">#{entry.title}</a></li>
9
9
  <?r end ?>
10
10
  </ul>
11
11
  <?r else ?>
@@ -1,57 +1,57 @@
1
1
  # * George Moschovitis <gm@navel.gr>
2
- # $Id: run.rb 267 2005-02-28 14:52:41Z gmosx $
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
- request['p'] = HP
21
+ @p = 'Home'
21
22
  show
22
23
  end
23
24
 
24
25
  def show
25
- p = request['p'].to_s
26
- o.h1(p)
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?p=#$&'>#$&</a>" }
31
- o.a 'Edit', :href => "edit?p=#{p}"
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?p=#{p}")
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.to_s }
42
- redirect "show?p=#{p}"
41
+ WIKI.transaction { WIKI[@p] = c }
42
+ redirect "/show/#@p"
43
43
  end
44
44
  WIKI.transaction do
45
- o.h1 "Editing #{p}"
46
- o.a('Show', :href => "show?p=#{p}").br.br
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 266 2005-02-28 14:50:48Z gmosx $
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.11.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
 
@@ -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