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.
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
@@ -3,14 +3,16 @@
3
3
  # $Id$
4
4
 
5
5
  module N
6
-
6
+
7
7
  require 'nitro/controller'
8
+ require 'nitro/routing'
8
9
  require 'nitro/simple'
9
10
 
10
11
  # The Dispatcher manages a set of controllers.
11
12
 
12
13
  class Dispatcher
13
-
14
+ include Router
15
+
14
16
  # The root directory.
15
17
 
16
18
  attr_accessor :root
@@ -34,15 +36,17 @@ class Dispatcher
34
36
  # [+apis+]
35
37
  # A hash of apis supported by the Dispatcher.
36
38
 
37
- def initialize(controllers = nil, apis = nil)
39
+ def initialize(controllers = nil, apis = nil, routes = nil)
38
40
  @root = 'root'
39
41
 
40
42
  if controllers and controllers.is_a?(Class) and controllers.ancestors.include?(Controller)
41
- @controllers = { :root => controllers }
43
+ controllers = { :root => controllers }
42
44
  else
43
- @controllers = controllers || { :root => SimpleController }
45
+ controllers ||= { :root => SimpleController }
44
46
  end
45
47
 
48
+ mount(controllers)
49
+
46
50
  @apis = apis || {}
47
51
  end
48
52
 
@@ -62,9 +66,11 @@ class Dispatcher
62
66
  # 'users' => UsersController # mounts /users
63
67
  # }
64
68
 
65
- def mount(controllers)
69
+ def add_controller(controllers)
66
70
  (@controllers ||= {}).update(controllers)
71
+ update_routes
67
72
  end
73
+ alias_method :mount, :add_controller
68
74
 
69
75
  # Add a new api to the dispatcher
70
76
  #
@@ -81,6 +87,21 @@ class Dispatcher
81
87
  (@apis ||= {})[api] = data
82
88
  end
83
89
 
90
+ # Update the routes. Typically called after a new
91
+ # Controller is mounted.
92
+
93
+ def update_routes
94
+ @routes = []
95
+ @controllers.each do |base, c|
96
+ base = (base == :root ? '' : "/#{base}")
97
+ c.action_metadata.each do |action, meta|
98
+ if route = meta[:route]
99
+ @routes << [route, "#{base}/#{action}", *meta.params.keys]
100
+ end
101
+ end
102
+ end
103
+ end
104
+
84
105
  # Processes the path and dispatches to the corresponding
85
106
  # controller/action pair.
86
107
  # The base returned contains a trailing '/'.
@@ -94,7 +115,10 @@ class Dispatcher
94
115
  def dispatch(path, context = nil)
95
116
  api = :xhtml
96
117
 
118
+ path = route(path, context)
119
+
97
120
  if @apis
121
+ # OPTIMIZE: check only if lookup fails.
98
122
  @apis.each { |k, v| api = k if path.slice!(/#{k}\//) }
99
123
  end
100
124
 
data/lib/nitro/markup.rb CHANGED
@@ -52,8 +52,6 @@ module PropertyUtils
52
52
  end
53
53
  end
54
54
 
55
- # = Markup
56
- #
57
55
  # Generalised Markup transformations.
58
56
  #
59
57
  # The expand methods evaluate (expand) the markup
@@ -76,6 +74,8 @@ module Markup
76
74
  return unless str
77
75
  str.gsub!(/"/, '&quot;')
78
76
  str.gsub!(/'/, '&#39;')
77
+ str.gsub!(/</, '&lt;')
78
+ str.gsub!(/>/, '&gt;')
79
79
  str.gsub!(/\r\n/, ' <br />')
80
80
  return str
81
81
  end
@@ -84,6 +84,8 @@ module Markup
84
84
  return unless str
85
85
  str.gsub!(/&quot;/, '"')
86
86
  str.gsub!(/&#39;/, "'")
87
+ str.gsub!(/&lt;/, '<')
88
+ str.gsub!(/&gt;/, '>')
87
89
  # gmosx: SOS! double quotes ARE needed for \r\n!!
88
90
  str.gsub!(/\s<br \/>/, "\r\n")
89
91
  return str
data/lib/nitro/render.rb CHANGED
@@ -4,8 +4,6 @@
4
4
 
5
5
  require 'sync'
6
6
 
7
- require 'nitro'
8
-
9
7
  require 'glue/attribute'
10
8
  require 'glue/misc'
11
9
  require 'glue/object'
@@ -118,10 +116,14 @@ module Rendering
118
116
  if klass.action_methods.include?(action)
119
117
  valid = true
120
118
 
121
- args = klass.action_method_arguments(action).map { |a| "@#{a} = @context['#{a}']" }
119
+ if meta = klass.action_metadata[action.intern]
120
+ params = meta.params.keys
121
+ params = params.collect { |p| "@#{p} = @context['#{p}']" }
122
+ code << "#{params.join(';')}"
123
+ end
122
124
 
123
125
  code << %{
124
- #{action}(#{args.join(',')});
126
+ #{action}
125
127
  }
126
128
  end
127
129
 
@@ -166,7 +168,9 @@ module Rendering
166
168
  end
167
169
  }
168
170
  end
169
-
171
+
172
+ # puts '---', code, '---'
173
+
170
174
  klass.class_eval(code)
171
175
  end
172
176
 
@@ -235,9 +239,8 @@ module Render
235
239
  # For example called by redirects.
236
240
 
237
241
  rescue Exception, StandardError => e
238
- log_error "Error while handling '#{path}'."
239
- log_error pp_exception(e)
240
-
242
+ log_error(e, path)
243
+
241
244
  # More fault tolerant, only flags the erroneous box with
242
245
  # error not the full page.
243
246
 
@@ -264,14 +267,15 @@ private
264
267
 
265
268
  # Log a rendering error.
266
269
 
267
- def log_error(str)
270
+ def log_error(error, path)
268
271
  @rendering_errors ||= []
269
- @rendering_errors << str
272
+ @rendering_errors << [error, path]
270
273
 
271
274
  # gmosx: Hmm perhaps this should not be logged
272
275
  # to avoid DOS attacks.
273
276
 
274
- Logger.error str
277
+ Logger.error "Error while handling '#{path}'."
278
+ Logger.error pp_exception(error)
275
279
  end
276
280
 
277
281
  # Convenience method to lookup the session.
@@ -0,0 +1,33 @@
1
+ # * George Moschovitis <gm@navel.gr>
2
+ # (c) 2004-2005 Navel, all rights reserved.
3
+ # $Id: routing.rb 271 2005-03-07 17:56:45Z gmosx $
4
+
5
+ module N
6
+
7
+ # Router mixin.
8
+
9
+ module Router
10
+
11
+ # The route table maps 'nice URLs' to real URLs that
12
+ # can be handled by the Dispatcher.
13
+
14
+ attr_accessor :routes
15
+
16
+ # Apply routing rules to the path.
17
+
18
+ def route(path, context)
19
+ for rule, real_path, *params in @routes
20
+ if md = path.match(rule)
21
+ params.each_with_index do |p, idx|
22
+ context[p] = md.captures[idx]
23
+ end
24
+ return real_path
25
+ end
26
+ end
27
+
28
+ return path
29
+ end
30
+
31
+ end
32
+
33
+ end
data/lib/nitro/runner.rb CHANGED
@@ -44,19 +44,28 @@ class Runner
44
44
  #
45
45
  # The default mode is :debug
46
46
 
47
- attr_accessor :mode
47
+ attr :mode
48
48
 
49
49
  # :start, :stop, :restart
50
50
 
51
- attr_accessor :action
51
+ attr :action
52
52
 
53
53
  # The server used to run this web application.
54
54
  # :webrick, :nitro, :lhttp, :apache, :mod_apache
55
55
  #
56
56
  # At the moment only :webrick and :lhttp are available.
57
57
 
58
- attr_accessor :server
58
+ attr :server
59
59
 
60
+ # Run as daemon.
61
+
62
+ attr :daemon
63
+
64
+ # Spidering mode. Acceptable values are :crawl, :render
65
+ # and false.
66
+
67
+ attr :spider
68
+
60
69
  # Parse the command line arguments and the environment
61
70
  # parameters to setup the application.
62
71
 
@@ -66,6 +75,7 @@ class Runner
66
75
  @action = :start
67
76
  @server = :webrick
68
77
  @daemon = false
78
+ @spider = false
69
79
 
70
80
  parser = OptionParser.new do |opts|
71
81
 
@@ -127,6 +137,16 @@ class Runner
127
137
  exit
128
138
  end
129
139
 
140
+ opts.on('--crawl', 'Crawl the application.') do
141
+ @server = :webrick
142
+ @spider = :crawl
143
+ end
144
+
145
+ opts.on('--render', 'Crawl the application and render all pages as static html files.') do
146
+ @server = :webrick
147
+ @spider = :render
148
+ end
149
+
130
150
  opts.on_tail('-v', '--version', 'Show version.') do
131
151
  puts "Nitro #{Nitro::Version}"
132
152
  exit
@@ -202,9 +222,24 @@ class Runner
202
222
  end
203
223
 
204
224
  def invoke_server(conf)
225
+ spider_thread = nil
226
+
205
227
  case @action
206
228
  when :start
207
229
 
230
+ case @spider
231
+ when :render
232
+ spider_thread = Thread.new do
233
+ sleep(6)
234
+ `wget -k -m -p #{conf.host}:#{conf.port} -directory-prefix=rendered`
235
+ end
236
+ when :crawl
237
+ spider_thread = Thread.new do
238
+ sleep(6)
239
+ `wget -m --spider #{conf.host}:#{conf.port}`
240
+ end
241
+ end
242
+
208
243
  puts "\n==> Application listening at #{conf.host}:#{conf.port}.\n\n"
209
244
 
210
245
  case @server
@@ -1,6 +1,6 @@
1
1
  # * George Moschovitis <gm@navel.gr>
2
2
  # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: scaffold.rb 248 2005-01-31 13:38:34Z gmosx $
3
+ # $Id: scaffold.rb 270 2005-03-07 17:52:16Z gmosx $
4
4
 
5
5
  require 'glue/inflector'
6
6
 
@@ -26,14 +26,15 @@ module Scaffolding
26
26
  oid = options[:oid] || 'oid'
27
27
  name = options[:name] || N::Inflector.name(klass.name)
28
28
  list_name = options[:list_name] || N::Inflector.plural_name(name)
29
- suffix = "_#{name}"
29
+ options[:nosuffix] ? suffix = nil : suffix = "_#{name}"
30
30
 
31
31
  # Add methods to the scaffolded class.
32
32
 
33
33
  klass.module_eval <<-"end_eval", __FILE__, __LINE__
34
34
 
35
35
  def view_uri
36
- "view#{suffix}?oid=\#\{@oid\}"
36
+ # "view#{suffix}?oid=\#\{@oid\}"
37
+ "view#{suffix}/\#\{@oid\}"
37
38
  end
38
39
 
39
40
  end_eval
@@ -59,8 +60,10 @@ module Scaffolding
59
60
  end
60
61
 
61
62
  def view#{suffix}
62
- @#{name} = #{klass}[@context['#{oid}']]
63
+ # @#{name} = #{klass}[@context['#{oid}']]
64
+ @#{name} = #{klass}[@#{oid}]
63
65
  end
66
+ action :view#{suffix}, :route => \%r\{view#{suffix}/(.*)\}, 'oid' => 1
64
67
 
65
68
  def save#{suffix}
66
69
  end
data/lib/nitro/shaders.rb CHANGED
@@ -1,8 +1,8 @@
1
- #--
2
1
  # George Moschovitis <gm@navel.gr>
3
2
  # (c) 2004-2005 Navel, all rights reserved.
4
3
  # $Id: shaders.rb 202 2005-01-17 10:44:13Z gmosx $
5
- #++
4
+
5
+ require 'nitro/template'
6
6
 
7
7
  module N
8
8
 
@@ -56,6 +56,7 @@ end
56
56
  # evaluated.
57
57
 
58
58
  class RubyShader < Shader
59
+ include TemplateMixin
59
60
 
60
61
  # Convert the xhtml script to actual Ruby code, ready to be
61
62
  # evaluated.
@@ -65,10 +66,16 @@ class RubyShader < Shader
65
66
  # perhaps xl:href should be used to be XLink compatible?
66
67
  #++
67
68
 
69
+ def process(hash, text)
70
+ text = compile_template(text)
71
+ process_next(hash, text)
72
+ end
73
+
74
+ =begin
68
75
  def process(hash, text)
69
76
  # strip the xml header! (interracts with the following gsub!)
70
77
  text.gsub!(/<\?xml.*\?>/, "")
71
-
78
+
72
79
  # Statically include sub script files.
73
80
  # The target file is included at compile time.
74
81
  #
@@ -134,6 +141,7 @@ class RubyShader < Shader
134
141
 
135
142
  process_next(hash, text)
136
143
  end
144
+ =end
137
145
 
138
146
  # Loads and statically includes a file.
139
147
 
@@ -223,4 +231,3 @@ class CompressShader < Shader
223
231
  end
224
232
 
225
233
  end
226
-
@@ -0,0 +1,140 @@
1
+ # * George Moschovitis <gm@navel.gr>
2
+ # (c) 2004-2005 Navel, all rights reserved.
3
+ # $Id: template.rb 271 2005-03-07 17:56:45Z gmosx $
4
+
5
+ module N
6
+
7
+ # A template is a text file with embeded Ruby code. The template
8
+ # processor converts the original text file to ruby code and
9
+ # then evaluates this code to produce the result of the
10
+ # template transformation.
11
+
12
+ module TemplateMixin
13
+
14
+ # Convert a template to actual Ruby code, ready to be
15
+ # evaluated.
16
+ #
17
+ # [+template+]
18
+ # The template as a String.
19
+ #
20
+ # [+buffer+]
21
+ # The variable to act as a buffer where the ruby code
22
+ # for this template will be generated. Passed as a|
23
+ # String.
24
+ #
25
+ # [+base_dir+]
26
+ # The base directory where the templates reside.
27
+
28
+ def compile_template(template, buffer = '@out', base_dir = Dir.pwd)
29
+ text = template.dup
30
+
31
+ # Strip the xml header! (interracts with the following gsub!)
32
+ text.gsub!(/<\?xml.*\?>/, "")
33
+
34
+ # Statically include sub-template files.
35
+ # The target file is included at compile time.
36
+ #
37
+ # gmosx: must be xformed before the <?r pi.
38
+ #
39
+ # Example:
40
+ # <?include href="root/myfile.sx" ?>
41
+
42
+ text.gsub!(/<\?include href="(.*?)"(.*)\?>/) do |match|
43
+ text = File.read("#{base_dir}/#$1")
44
+ text.gsub!(/<\?xml.*\?>/, '')
45
+ text.gsub!(/<\/?root(.*?)>/m, ' ');
46
+ text
47
+ end
48
+
49
+ # Transform include instructions <include href="xxx" />
50
+ # must be transformed before the processinc instructions.
51
+ # Useful to include fragments cached on disk
52
+ #
53
+ # gmosx, FIXME: NOT TESTED! test and add caching.
54
+ # add load_statically_included fixes.
55
+
56
+ text.gsub!(/<include href="(.*?)"(.*)(.?)\/>/) do |match|
57
+ "<?r File.read( '\#\{@dispatcher.root\}/#$1' ?>"
58
+ end
59
+
60
+ # xform render/inject instructions <render href="xxx" />
61
+ # must be transformed before the processinc instructions.
62
+
63
+ text.gsub!(/<inject href="(.*?)"(.*)(.?)\/>/) do |match|
64
+ "<?r render '/#$1' ?>"
65
+ end
66
+
67
+ text.gsub!(/<render href="(.*?)"(.*)(.?)\/>/) do |match|
68
+ "<?r render '/#$1' ?>"
69
+ end
70
+
71
+ # Remove <root> elements. typically removed by xslt but lets
72
+ # play it safe. The <root> element is typically added to
73
+ # template files to make them XHTML valid.
74
+
75
+ text.gsub!(/<(\/)?root>/, '')
76
+
77
+ # Transform the processing instructions, use <?r as
78
+ # a marker.
79
+
80
+ text.gsub!(/\?>/, "\n#{buffer} << %^")
81
+ text.gsub!(/<\?r(\s?)/, "^\n")
82
+
83
+ # Transform alternative code tags.
84
+ # (very useful in xsl stylesheets)
85
+
86
+ text.gsub!(/<\/ruby>/, "\n#{buffer} << %^")
87
+ text.gsub!(/<ruby>/, "^\n")
88
+
89
+ # Alterative versions of interpolation.
90
+ # (very useful in xsl stylesheets)
91
+
92
+ text.gsub!(/\#\((.*?)\)/, '#{\1}')
93
+
94
+ # Compile time ruby code. This code is evaluated when
95
+ # compiling the template and the result injected directly
96
+ # into the result. Usefull for example to prevaluate
97
+ # localization.
98
+
99
+ text.gsub!(/\#\[(.*?)\]/) do |match|
100
+ eval($1)
101
+ end
102
+
103
+ text = "#{buffer} << %^" + text + "^"
104
+
105
+ return text
106
+ end
107
+
108
+ # Render the template.
109
+ #
110
+ # [+ruby+]
111
+ # A String containing the compiled template
112
+ # code.
113
+ #
114
+ # [+binding+]
115
+ # The evaluation binding for the rendering.
116
+
117
+ def render_template(ruby, the_binding = nil)
118
+ eval(ruby, the_binding)
119
+ end
120
+
121
+ # Compile and render the template.
122
+
123
+ def process_template(template, buffer = '@out', the_binding = nil)
124
+ render_template(compile_template(template, buffer), the_binding)
125
+ end
126
+
127
+ end
128
+
129
+ # A template class implementing the Template mixin.
130
+
131
+ class Template
132
+ class << self
133
+ include TemplateMixin
134
+ alias_method :compile, :compile_template
135
+ alias_method :render, :render_template
136
+ alias_method :process, :process_template
137
+ end
138
+ end
139
+
140
+ end