nitro 0.28.0 → 0.29.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 (73) hide show
  1. data/CHANGELOG +382 -0
  2. data/ProjectInfo +4 -4
  3. data/README +1 -1
  4. data/doc/AUTHORS +15 -15
  5. data/doc/MIGRATION +13 -0
  6. data/doc/RELEASES +102 -0
  7. data/lib/glue/sweeper.rb +1 -1
  8. data/lib/nitro.rb +38 -9
  9. data/lib/nitro/adapter/acgi.rb +1 -3
  10. data/lib/nitro/adapter/cgi.rb +1 -1
  11. data/lib/nitro/adapter/fastcgi.rb +1 -3
  12. data/lib/nitro/adapter/mongrel.rb +8 -6
  13. data/lib/nitro/adapter/webrick.rb +1 -2
  14. data/lib/nitro/cgi.rb +1 -1
  15. data/lib/nitro/compiler.rb +21 -40
  16. data/lib/nitro/compiler/elements.rb +72 -32
  17. data/lib/nitro/compiler/errors.rb +92 -42
  18. data/lib/nitro/compiler/include.rb +47 -17
  19. data/lib/nitro/compiler/morphing.rb +1 -3
  20. data/lib/nitro/compiler/script.rb +2 -2
  21. data/lib/nitro/context.rb +36 -0
  22. data/lib/nitro/controller.rb +140 -31
  23. data/lib/nitro/dispatcher.rb +27 -28
  24. data/lib/nitro/element.rb +52 -15
  25. data/lib/nitro/flash.rb +44 -0
  26. data/lib/nitro/helper/buffer.rb +0 -2
  27. data/lib/nitro/helper/form.rb +2 -2
  28. data/lib/nitro/helper/form/controls.rb +14 -3
  29. data/lib/nitro/helper/pager.rb +1 -1
  30. data/lib/nitro/helper/table.rb +4 -3
  31. data/lib/nitro/helper/xml.rb +1 -1
  32. data/lib/nitro/part.rb +20 -0
  33. data/lib/nitro/render.rb +44 -5
  34. data/lib/nitro/router.rb +81 -0
  35. data/lib/nitro/scaffolding.rb +24 -23
  36. data/lib/nitro/server.rb +12 -1
  37. data/lib/nitro/server/runner.rb +12 -0
  38. data/lib/nitro/session.rb +3 -12
  39. data/lib/nitro/session/drb.rb +2 -5
  40. data/lib/nitro/session/file.rb +2 -2
  41. data/lib/nitro/session/memcached.rb +14 -0
  42. data/lib/nitro/session/memory.rb +3 -26
  43. data/lib/nitro/session/og.rb +1 -1
  44. data/lib/nitro/test/assertions.rb +1 -1
  45. data/lib/nitro/test/context.rb +8 -2
  46. data/lib/nitro/test/testcase.rb +16 -7
  47. data/proto/public/error.xhtml +58 -21
  48. data/proto/public/js/controls.js +60 -15
  49. data/proto/public/js/dragdrop.js +105 -16
  50. data/proto/public/js/effects.js +19 -12
  51. data/proto/public/js/scriptaculous.js +1 -1
  52. data/proto/public/js/slider.js +2 -2
  53. data/proto/public/js/unittest.js +29 -20
  54. data/proto/public/scaffold/edit.xhtml +1 -1
  55. data/proto/public/scaffold/index.xhtml +2 -2
  56. data/proto/public/scaffold/list.xhtml +2 -2
  57. data/proto/public/scaffold/new.xhtml +1 -1
  58. data/proto/public/scaffold/search.xhtml +1 -1
  59. data/src/part/admin/controller.rb +5 -5
  60. data/src/part/admin/template/index.xhtml +2 -2
  61. data/test/nitro/compiler/tc_compiler.rb +23 -0
  62. data/test/nitro/helper/tc_table.rb +35 -0
  63. data/test/nitro/tc_cgi.rb +1 -1
  64. data/test/nitro/tc_controller.rb +3 -3
  65. data/test/nitro/tc_controller_aspect.rb +2 -0
  66. data/test/nitro/tc_dispatcher.rb +10 -1
  67. data/test/nitro/tc_flash.rb +14 -0
  68. data/test/nitro/tc_router.rb +58 -0
  69. data/test/nitro/tc_session.rb +26 -9
  70. metadata +13 -12
  71. data/lib/nitro/routing.rb +0 -41
  72. data/test/nitro/caching/tc_stores.rb +0 -17
  73. data/test/nitro/tc_table.rb +0 -66
@@ -10,6 +10,19 @@ For more help, send your question to the mailing list:
10
10
  http://rubyforge.org/mailman/listinfo/nitro-general
11
11
 
12
12
 
13
+ == 0.29.0 <- 0.28.0
14
+
15
+ 1. Please notice that Tag now resides in the Glue namespace, you
16
+ will probably have to update your tables.
17
+
18
+ 2. You have to be more careful with the hrefs you pass to
19
+ <render > and <?include ?>. Some times you have to pass
20
+ absolute paths (ie /this/is/my path) to get the correct
21
+ behaviour. Nitro is more strict in this version.
22
+
23
+ 3. The routing rule format has changed slightly.
24
+
25
+
13
26
  == 0.27.0 <- 0.26.0
14
27
 
15
28
  1. If you use a custom compiler pipeline, notice that the interface
@@ -1,3 +1,105 @@
1
+ == Version 0.29.0
2
+
3
+ A bold step towards maturity. Great care was taken to
4
+ fix reported bugs and fine tune many aspects of Nitro and Og.
5
+ As always some great new features where added. Special thanks fly
6
+ to Jonas Pfenniger, Bryan Sotto, Rob Pitt and Guillaume
7
+ Pierronnet for making this release possible.
8
+
9
+ Most notable changes:
10
+
11
+ * Greatly improved error detection and report. Nitro now provides
12
+ line exact error reports at compile or run time, in actions
13
+ or templates. Stay tuned for more improvements in error
14
+ handling.
15
+
16
+ * Nitro now supports a very useful url endoding/decoding system
17
+ along with a Camping inspired R operator. This new system allows
18
+ you to refer to controllers and actions in your code, without
19
+ bothering about the enforced nice urls and rewrite/routing
20
+ rules. This allows you to write more robust code.
21
+
22
+ Here are some examples:
23
+
24
+ redirect R(UsersController, :login, :name, 'gmosx')
25
+ <a href="#{R(ForaController, :delete, :id, 3)}">delete</a>
26
+
27
+ some more helpers and better integration of this feature
28
+ will be available soon.
29
+
30
+ * To better support the URL codec, a new router was implemented.
31
+ The new version is both more powerfull and faster. Here are
32
+ some examples:
33
+
34
+ r.add_route(%r{rewritten/url/(.*)}, :controller => IdController, :action => :register, :param => :name)
35
+ r.add_route(%r{another/zelo/(.*)/(.*)}, :controller => AdminController, :action => :kick, :params => [:name, :age])
36
+ r.add_route(%r{cool/(.*)_(.*).html}, :controller => AdminController, :action => :long, :params => [:name, :age])
37
+
38
+ * Og now supports calculations and aggregations. Here are some
39
+ examples:
40
+
41
+ User.min(:age)
42
+ User.average(:age)
43
+ User.maximum(:age)
44
+ User.min(:age, :group => :profession) # => [..] (aggregation)
45
+ User.sum(:age, :group => :role) # => [..]
46
+
47
+ and more!
48
+
49
+ * Improved template_root handling. Now Nitro automatically generates
50
+ a template_root stack for each controller / publishable object.
51
+ Of course the developer can fully customize this stack.
52
+ This is great for reusable modules of functionality (parts). Lets
53
+ say you have implemented a forum part. When you 'mount' the
54
+ forum controller a path relative to the mount point is pushed
55
+ in the template_root stack. When the dispatcher searches for
56
+ a template, it traverses the stack. In the described scenario
57
+ it first looks in the application template root, next in a template
58
+ root the points inside the part template root and then in the
59
+ proto dir template root. The proto dir template root is automatically
60
+ pushed as the last root in the stack. This system facilitates
61
+ 'object oriented sites'.
62
+
63
+ Use the following method to customize the template_root.
64
+
65
+ def self.setup_template_root(path)
66
+ ...
67
+ end
68
+
69
+ * Added support for JSP like application scoped (global)
70
+ variables.
71
+
72
+ def login
73
+ ...
74
+ global[:users] << current_user
75
+ application[:users] << current_user
76
+ ...
77
+ end
78
+
79
+ The global/application hash is backed by any of the available
80
+ cache stores.
81
+
82
+ * Improved Taggable mixin, now provides more helpers and supports
83
+ tag garbage collection through reference counting.
84
+
85
+ * Added a new store for the generalized caching system that is
86
+ backed by a MemCache server. Useful to extract the last ounch
87
+ of performance in a production environment.
88
+
89
+ * Fixes in the SCGI adapter.
90
+
91
+ * Many Og bug fixes and optimizations.
92
+
93
+ * More flexible static include compiler.
94
+
95
+ * Improved testing support.
96
+
97
+ * Integrated latest versions of Scriptaculous and Facets.
98
+
99
+ * Many, many bug fixes and small improvements throughout the
100
+ code.
101
+
102
+
1
103
  == Version 0.28.0
2
104
 
3
105
  A snapshot of the latest developments. As always, cool new
@@ -12,7 +12,7 @@ module Glue
12
12
  #++
13
13
 
14
14
  module Sweeper
15
- include Aspects
15
+ include Glue::Aspects
16
16
 
17
17
  before "sweep_affected(:insert)", :on => :og_insert
18
18
  before "sweep_affected(:update)", :on => :og_update
@@ -16,7 +16,7 @@ module Nitro
16
16
 
17
17
  # The version.
18
18
 
19
- Version = '0.28.0'
19
+ Version = '0.29.0'
20
20
 
21
21
  # Library path.
22
22
 
@@ -29,6 +29,10 @@ module Nitro
29
29
  # Add the src dir in the path.
30
30
 
31
31
  $LOAD_PATH.unshift File.join(LibPath, '..', 'src')
32
+
33
+ # Include the Glue namespace in Nitro
34
+
35
+ include Glue
32
36
  end
33
37
 
34
38
  #--
@@ -40,6 +44,7 @@ require 'nitro/controller'
40
44
  require 'nitro/dispatcher'
41
45
  require 'nitro/render'
42
46
  require 'nitro/server'
47
+ require 'nitro/part'
43
48
 
44
49
  unless $NITRO_NO_ENVIRONMENT
45
50
  # Setup up the proposed environment. You are free
@@ -49,18 +54,17 @@ unless $NITRO_NO_ENVIRONMENT
49
54
  #
50
55
  # before requiring nitro.
51
56
 
52
- # if $0 # mod_ruby set $0 to false
53
- # Put the start file dir in the path.
54
- Dir.chdir(File.dirname($0))
57
+ # Put the start file dir in the path.
55
58
 
56
- # Application code come here.
59
+ Dir.chdir(File.dirname($0))
57
60
 
58
- $LOAD_PATH.unshift 'src'
61
+ # Application code come here.
59
62
 
60
- # Library code come here.
63
+ $LOAD_PATH.unshift 'src'
61
64
 
62
- $LOAD_PATH.unshift 'lib'
63
- # end
65
+ # Library code come here.
66
+
67
+ $LOAD_PATH.unshift 'lib'
64
68
  end
65
69
 
66
70
  module Nitro
@@ -73,6 +77,31 @@ module Nitro
73
77
  Server.run(controller)
74
78
  end
75
79
  alias_method :start, :run
80
+
81
+ # A helper to get the current execution mode.
82
+
83
+ def mode
84
+ Runner.mode
85
+ end
86
+ alias_method :execution_mode, :mode
87
+
88
+
89
+ # A helper method.
90
+
91
+ def live?
92
+ Runner.mode == :live
93
+ end
94
+ alias_method :production?, :live?
95
+
76
96
  end
97
+
98
+ # Cache for application scoped (global) variables. This is a
99
+ # temporal store, will be moved to the actuall cache in
100
+ # Server.start
101
+
102
+ $global = $application = {}
77
103
 
78
104
  end
105
+
106
+
107
+ # * George Moschovitis <gm@navel.gr>
@@ -8,15 +8,13 @@ require 'nitro/context'
8
8
  require 'nitro/dispatcher'
9
9
  require 'nitro/cgi'
10
10
 
11
- require 'glue/flexob'
12
-
13
11
  # Speeds things up, more comaptible with OSX.
14
12
 
15
13
  Socket.do_not_reverse_lookup = true
16
14
 
17
15
  # No multi-threading.
18
16
 
19
- Og.thread_safe = false
17
+ Og.thread_safe = false if defined?(Og) and Og.respond_to?(:thread_safe)
20
18
 
21
19
  module Nitro
22
20
 
@@ -18,7 +18,7 @@ Socket.do_not_reverse_lookup = true
18
18
 
19
19
  # No multi-threading.
20
20
 
21
- Og.thread_safe = false
21
+ Og.thread_safe = false if defined?(Og) and Og.respond_to?(:thread_safe)
22
22
 
23
23
  module Nitro
24
24
 
@@ -5,15 +5,13 @@ require 'nitro/context'
5
5
  require 'nitro/dispatcher'
6
6
  require 'nitro/cgi'
7
7
 
8
- require 'glue/flexob'
9
-
10
8
  # Speeds things up, more comaptible with OSX.
11
9
 
12
10
  Socket.do_not_reverse_lookup = true
13
11
 
14
12
  # No multi-threading.
15
13
 
16
- Og.thread_safe = false
14
+ Og.thread_safe = false if defined?(Og) and Og.respond_to?(:thread_safe)
17
15
 
18
16
  module Nitro
19
17
 
@@ -1,8 +1,8 @@
1
1
  require 'stringio'
2
2
 
3
3
  require 'mongrel'
4
+ require 'mongrel/handlers'
4
5
 
5
- require 'glue/flexob'
6
6
  require 'nitro/cgi'
7
7
  require 'nitro/context'
8
8
  require 'nitro/dispatcher'
@@ -58,7 +58,8 @@ class Mongrel
58
58
 
59
59
  initialize_mongrel(server)
60
60
 
61
- @mongrel_thread = @mongrel.run
61
+ @mongrel.run
62
+ @mongrel_thread = @mongrel.acceptor
62
63
  @mongrel_thread.join
63
64
  end
64
65
 
@@ -93,7 +94,7 @@ class MongrelAdapter < ::Mongrel::HttpHandler
93
94
  attr_accessor :server
94
95
 
95
96
  STATUS_CODES = {
96
- 200 => "OK", "304" => "Not Modified",
97
+ "200" => "OK", "304" => "Not Modified",
97
98
  "404" => "Not found", "500" => "Server Error"
98
99
  }
99
100
 
@@ -112,12 +113,13 @@ class MongrelAdapter < ::Mongrel::HttpHandler
112
113
  rewrite(req)
113
114
  # TODO handle If-Modified-Since and add Last-Modified headers
114
115
  filename = [@server.public_root, req.path_info].join("/")
115
- File.open(filename, "r") { |f|
116
- # TODO look up mime type
116
+ ext = File.extname(filename)
117
+ content_type = ::Mongrel::DirHandler::MIME_TYPES[ext] || "text/plain"
118
+ File.open(filename, "rb") { |f|
117
119
  # TODO check whether path circumvents public_root directory?
118
120
  size = File.size(filename)
119
121
  res.socket << "HTTP/1.1 200 OK\r\n"
120
- res.socket << "Content-type: text/plain\r\n"
122
+ res.socket << "Content-type: #{content_type}\r\n"
121
123
  res.socket << "Content-length: #{size}\r\n"
122
124
  res.socket << "\r\n"
123
125
  res.socket << f.read # XXX inefficient for large files, may cause leaks
@@ -1,7 +1,6 @@
1
1
  require 'webrick'
2
2
  require 'stringio'
3
3
 
4
- require 'glue/flexob'
5
4
  require 'nitro/cgi'
6
5
  require 'nitro/context'
7
6
  require 'nitro/dispatcher'
@@ -141,8 +140,8 @@ class WebrickAdapter < WEBrick::HTTPServlet::AbstractServlet
141
140
  context.headers.update(req.meta_vars)
142
141
 
143
142
  # gmosx: make compatible with fastcgi.
143
+
144
144
  context.headers['REQUEST_URI'].slice!(/http:\/\/(.*?)\//)
145
- # context.headers['REQUEST_URI'] << '/'
146
145
  context.headers['REQUEST_URI'] = '/' + context.headers['REQUEST_URI']
147
146
 
148
147
  Cgi.parse_params(context)
@@ -70,7 +70,7 @@ class Cgi
70
70
  params[$1] = structure_param(params[$1], $2, val)
71
71
  elsif key =~ /(.+)\[\]$/
72
72
  params[$1] ||= Array.new
73
- params[$1] << val
73
+ params[$1] << val.to_s
74
74
  else
75
75
  params[key] = val.nil? ? nil : val
76
76
  end
@@ -1,7 +1,8 @@
1
1
  require 'glue/template'
2
2
 
3
- require 'nitro/compiler/elements'
4
3
  require 'nitro/compiler/errors'
4
+
5
+ require 'nitro/compiler/elements'
5
6
  require 'nitro/compiler/markup'
6
7
  require 'nitro/compiler/morphing'
7
8
  require 'nitro/compiler/script'
@@ -44,31 +45,17 @@ class Compiler
44
45
  @shared = {}
45
46
  end
46
47
 
48
+ # Traverse the template_root stack to find a template for
49
+ # this action.
50
+ #
47
51
  # Action names with double underscores (__) are converted
48
52
  # to subdirectories. Here are some example mappings:
49
53
  #
50
54
  # hello_world -> template_root/hello_world.xhtml
51
55
  # this__is__my__hello_world -> template_root/this/is/my/hello_world
52
56
 
53
- def template_for_action(action, ext = Template.extension)
54
- cklass = @controller
55
- template_root = nil
56
- checked_proto = nil
57
-
58
- # search for template in controller and its ancestors's template_root
59
- # if there is not an action defined in controller then also check in
60
- # PROTO_TEMPLATE_ROOT
61
-
62
- loop do
63
- if cklass.respond_to?(:template_root) && template_root = cklass.template_root
64
- cklass = cklass.superclass
65
- elsif !@controller.respond_to?(:action) && !checked_proto
66
- template_root = PROTO_TEMPLATE_ROOT
67
- checked_proto = true
68
- else
69
- return nil # no template found
70
- end
71
-
57
+ def template_for_action(action, ext = Glue::Template.extension)
58
+ for template_root in @controller.instance_variable_get(:@template_root)
72
59
  # attempt to find a template of the form
73
60
  # template_root/action.xhtml
74
61
 
@@ -78,9 +65,10 @@ class Compiler
78
65
  # attempt to find a template of the form
79
66
  # template_root/action/index.xhtml
80
67
 
81
- path = "#{template_root}/#{action.gsub(/__/, '/')}/#{Template.default}.#{ext}".squeeze('/')
68
+ path = "#{template_root}/#{action.gsub(/__/, '/')}/#{Glue::Template.default}.#{ext}".squeeze('/')
82
69
  return path if File.exist?(path)
83
70
  end
71
+ return nil
84
72
  end
85
73
  alias_method :template?, :template_for_action
86
74
 
@@ -100,7 +88,7 @@ class Compiler
100
88
  # Morphing, Elements and Markup compiler modules.
101
89
 
102
90
  def transform_template(template)
103
- template = StaticInclude.transform(template)
91
+ template = StaticInclude.transform(template, self)
104
92
  template = Morphing.transform(template, self)
105
93
  # template = LayoutCompiler.transform(template, self)
106
94
  template = Elements.transform(template, self)
@@ -124,12 +112,8 @@ class Compiler
124
112
  #{transform_template(template)}
125
113
  end
126
114
  }
127
-
128
- begin
129
- @controller.class_eval(code, path)
130
- rescue SyntaxError => e
131
- raise TemplateCompileError.new(code, template, e)
132
- end
115
+
116
+ @controller.class_eval(code, path)
133
117
  end
134
118
 
135
119
  # Compiles an action. The generated action combines the
@@ -150,7 +134,7 @@ class Compiler
150
134
  #
151
135
  # This generated method is called by the dispatcher.
152
136
  #
153
- # === Template root overloading
137
+ # === Glue::Template root overloading
154
138
  #
155
139
  # Nitro provides a nice method of template_root overloading
156
140
  # that allows you to use OOP principles with templates.
@@ -187,7 +171,7 @@ class Compiler
187
171
 
188
172
  # Inject the pre advices.
189
173
 
190
- code << Aspects.gen_advice_code(action, @controller.advices, :pre)
174
+ code << Glue::Aspects.gen_advice_code(action, @controller.advices, :pre)
191
175
 
192
176
  # Call the action
193
177
 
@@ -204,7 +188,7 @@ class Compiler
204
188
  # Try to resolve action parameters. Returns negative
205
189
  # numbers for arbitrary parameters.
206
190
 
207
- param_count = @controller.instance_method(action.intern).arity
191
+ param_count = @controller.instance_method(action.to_sym).arity
208
192
 
209
193
  if param_count != 0
210
194
  if param_count > 0
@@ -224,7 +208,7 @@ class Compiler
224
208
  end
225
209
  code << %{
226
210
  break if qs.index('=') and not is_hash
227
- params[i] = CGI.unescape(qs.split(/=/).last)
211
+ params[i] = CGI.unescape(qs.split(/=/).last || "")
228
212
  end
229
213
  end
230
214
  action_return_value = #{action}(*params)
@@ -283,7 +267,7 @@ class Compiler
283
267
 
284
268
  # Inject the post advices.
285
269
 
286
- code << Aspects.gen_advice_code(action, @controller.advices, :post)
270
+ code << Glue::Aspects.gen_advice_code(action, @controller.advices, :post)
287
271
 
288
272
  code << %{
289
273
  @action_name = @parent_action_name
@@ -292,11 +276,7 @@ class Compiler
292
276
 
293
277
  # First compile the action method.
294
278
 
295
- # begin
296
- @controller.class_eval(code)
297
- # rescue SyntaxError => e
298
- # raise ActionCompileError.new(code, action, e)
299
- # end
279
+ @controller.class_eval(code)
300
280
 
301
281
  unless @controller.respond_to?("#{action}_template")
302
282
  if template_path
@@ -329,12 +309,12 @@ class Compiler
329
309
  # Typically used to precompile css templates.
330
310
 
331
311
  def precompile(filename)
332
- src = File.join(Template.root, "#{filename}t")
312
+ src = File.join(Glue::Template.root, "#{filename}t")
333
313
  dst = File.join(Server.public_root, filename)
334
314
 
335
315
  if (!File.exist?(dst)) or (File.mtime(src) > File.mtime(dst))
336
316
  Logger.info "Compiling template '#{src}' to '#{dst}'."
337
- template = FileTemplate.new(src)
317
+ template = Glue::FileTemplate.new(src)
338
318
  File.open(dst, 'w') do |f|
339
319
  f << template.process
340
320
  end
@@ -349,3 +329,4 @@ end
349
329
 
350
330
  # * George Moschovitis <gm@navel.gr>
351
331
  # * Chris Farmiloe <chris.farmiloe@farmiloe.com>
332
+ # * Rob Pitt <rob@motionpath.co.uk>