nitro 0.27.0 → 0.28.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 +276 -0
  2. data/ProjectInfo +4 -4
  3. data/README +9 -1
  4. data/Rakefile +1 -1
  5. data/doc/AUTHORS +30 -17
  6. data/doc/RELEASES +110 -23
  7. data/lib/glue/sweeper.rb +1 -1
  8. data/lib/glue/webfile.rb +1 -1
  9. data/lib/nitro.rb +1 -1
  10. data/lib/nitro/adapter/acgi.rb +5 -1
  11. data/lib/nitro/adapter/cgi.rb +4 -0
  12. data/lib/nitro/adapter/fastcgi.rb +12 -1
  13. data/lib/nitro/adapter/mongrel.rb +219 -0
  14. data/lib/nitro/adapter/scgi.rb +62 -69
  15. data/lib/nitro/caching.rb +6 -5
  16. data/lib/nitro/caching/actions.rb +14 -8
  17. data/lib/nitro/caching/fragments.rb +32 -17
  18. data/lib/nitro/caching/output.rb +10 -2
  19. data/lib/nitro/cgi.rb +7 -3
  20. data/lib/nitro/cgi/stream.rb +1 -3
  21. data/lib/nitro/compiler.rb +5 -4
  22. data/lib/nitro/compiler/errors.rb +1 -1
  23. data/lib/nitro/compiler/morphing.rb +2 -2
  24. data/lib/nitro/compiler/script.rb +1 -1
  25. data/lib/nitro/context.rb +8 -2
  26. data/lib/nitro/controller.rb +1 -1
  27. data/lib/nitro/dispatcher.rb +0 -2
  28. data/lib/nitro/element.rb +5 -5
  29. data/lib/nitro/flash.rb +1 -1
  30. data/lib/nitro/helper.rb +2 -2
  31. data/lib/nitro/helper/form.rb +1 -1
  32. data/lib/nitro/helper/form/controls.rb +2 -1
  33. data/lib/nitro/helper/javascript.rb +1 -1
  34. data/lib/nitro/helper/javascript/morphing.rb +1 -1
  35. data/lib/nitro/helper/layout.rb +1 -1
  36. data/lib/nitro/helper/pager.rb +7 -3
  37. data/lib/nitro/helper/rss.rb +1 -1
  38. data/lib/nitro/render.rb +1 -1
  39. data/lib/nitro/scaffolding.rb +26 -4
  40. data/lib/nitro/server/drb.rb +106 -0
  41. data/lib/nitro/server/runner.rb +23 -2
  42. data/lib/nitro/session.rb +33 -16
  43. data/lib/nitro/session/drb.rb +6 -20
  44. data/lib/nitro/session/file.rb +4 -49
  45. data/lib/nitro/session/memory.rb +16 -0
  46. data/lib/nitro/session/og.rb +4 -46
  47. data/src/part/admin/controller.rb +2 -3
  48. data/src/part/admin/template/index.xhtml +1 -1
  49. data/test/nitro/tc_cgi.rb +72 -3
  50. data/test/nitro/tc_render.rb +1 -1
  51. data/test/nitro/tc_session.rb +16 -15
  52. metadata +12 -14
  53. data/lib/nitro/caching/invalidation.rb +0 -25
  54. data/lib/nitro/caching/stores.rb +0 -94
  55. data/lib/nitro/helper/form/test.xhtml +0 -0
  56. data/lib/nitro/session/drbserver.rb +0 -84
@@ -1,5 +1,3 @@
1
- require 'fileutils'
2
-
3
1
  require 'glue/attribute'
4
2
  require 'glue/configuration'
5
3
  require 'glue/sweeper'
@@ -10,7 +8,11 @@ require 'nitro/caching/fragments'
10
8
 
11
9
  module Nitro
12
10
 
13
- # Adds support for caching.
11
+ # Nitro Hierarchical Caching system.
12
+ #
13
+ # # Output caching (caches the whole page, main action)
14
+ # # Action caching (cache the fragment generated by an action)
15
+ # # Fragment caching (fine-grained fragment caching, cache snippets of code)
14
16
  #--
15
17
  # TODO: add per controller caching_enabled.
16
18
  #++
@@ -21,8 +23,7 @@ module Caching
21
23
 
22
24
  setting :caching_enabled, :default => true, :doc => 'Globaly enable/disable caching'
23
25
 
24
- def self.append_features(base) #:nodoc:
25
- super
26
+ def self.included(base) #:nodoc:
26
27
  base.send :include, Output, Actions, Fragments
27
28
  base.module_eval do
28
29
  # @caching_enabled = true
@@ -1,17 +1,21 @@
1
1
  require 'fileutils'
2
2
 
3
+ require 'nitro/caching/fragments'
4
+
3
5
  module Nitro
4
6
 
5
7
  # Adds support for caching.
6
8
 
7
9
  module Caching
8
10
 
9
- # Action caching.
11
+ # Action caching is a set of helper to allow the caching
12
+ # generated by an action. In the caching hierarchy it lies
13
+ # between Output caching (top action, full page) and fragment
14
+ # caching (fine-grained caching).
10
15
 
11
16
  module Actions
12
17
 
13
- def self.append_features(base) # :nodoc:
14
- super
18
+ def self.included(base) # :nodoc:
15
19
  base.extend(ClassMethods)
16
20
  end
17
21
 
@@ -20,10 +24,10 @@ module Caching
20
24
  def cache_action(*actions)
21
25
  return unless caching_enabled?
22
26
 
23
- before_filter(
27
+ before(
24
28
  %{
25
29
  fragment_name = "\#\{@action_name\}\#{@request.query_string}"
26
- if fragment = Fragment.get(fragment_name)
30
+ if fragment = Fragments.get(fragment_name)
27
31
  @out = fragment
28
32
  return
29
33
  end
@@ -31,10 +35,10 @@ module Caching
31
35
  :only => actions
32
36
  )
33
37
 
34
- after_filter(
38
+ after(
35
39
  %{
36
40
  fragment_name = "\#\{@action_name\}\#{@request.query_string}"
37
- Fragment.put(fragment_name, @out)
41
+ Fragments.put(fragment_name, @out)
38
42
  },
39
43
  :only => actions
40
44
  )
@@ -44,8 +48,10 @@ module Caching
44
48
 
45
49
  private
46
50
 
51
+ # Expire the cached fragment of the given actions.
52
+ #
47
53
  #--
48
- # FIXME: not implemented.
54
+ # FIXME: not very good implementation?
49
55
  #++
50
56
 
51
57
  def expire_action(*actions)
@@ -1,7 +1,8 @@
1
1
  require 'fileutils'
2
2
 
3
+ require 'glue/configuration'
3
4
  require 'glue/attribute'
4
- require 'nitro/caching/stores'
5
+ require 'glue/cache/memory'
5
6
 
6
7
  module Nitro
7
8
 
@@ -10,40 +11,53 @@ module Nitro
10
11
  module Caching
11
12
 
12
13
  # Action caching. Caches a fragment, ie a page part.
13
- # Use output cachingfor full page caching.
14
+ # Use output caching for full page caching.
14
15
 
15
16
  module Fragments
16
17
 
17
- @@store = FileStore.new # MemoryStore.new
18
-
19
- def self.store
20
- @@store
21
- end
18
+ # The cache used to store the fragments.
22
19
 
23
- def self.store=(store)
24
- @@store = store
25
- end
20
+ setting :cache, :default => nil, :doc => 'The cache used to store the fragments'
21
+
22
+ #--
23
+ # gmosx, FIXME: this is a hack, improve setting
24
+ # implementation.
25
+ #++
26
+
27
+ @@cache = Glue::MemoryCache.new
26
28
 
27
29
  def self.get(name, options = {})
28
- return @@store.read(name, options)
30
+ return @@cache.get(name, options)
29
31
  end
30
32
 
31
33
  def self.put(name, content = nil, options = {})
32
- @@store.write(name, content, options)
34
+ @@cache.put(name, content, options)
33
35
  return content
34
36
  end
35
37
 
36
- def self.append_features(base) # :nodoc:
37
- super
38
- end
39
-
40
38
  private
41
39
 
40
+ # Helper method to cache a fragment.
41
+ #
42
+ # === Example
43
+ #
44
+ # ...
45
+ # <h1>Article list</h1>
46
+ #
47
+ # <?r cache(:my_cache_key) do ?>
48
+ # <ul>
49
+ # <li each="a in Article.all">#{a.title}</li>
50
+ # </ul>
51
+ # <?r end ?>
52
+ # ...
53
+
42
54
  def cache(name = nil, options = {}, &block)
43
55
  name = @action_name unless name
44
56
  cache_fragment(block, "#{name}#{options}", options)
45
57
  end
46
58
 
59
+ # Internal method, prefer to use cache instead.
60
+
47
61
  def cache_fragment(block, name, options = {})
48
62
  unless caching_enabled?
49
63
  block.call
@@ -59,13 +73,14 @@ module Caching
59
73
  end
60
74
  end
61
75
 
76
+ # Expire a cached fragment.
62
77
  #--
63
78
  # gmosx: If you modify the code here, don't forget to modify
64
79
  # the same method on the sweeper.
65
80
  #++
66
81
 
67
82
  def expire_fragment(name, options = {})
68
- Fragments.store.delete(name, options)
83
+ Fragments.cache.delete(name, options)
69
84
  end
70
85
  end
71
86
 
@@ -6,12 +6,20 @@ module Nitro
6
6
 
7
7
  module Caching
8
8
 
9
- # Output caching.
9
+ # The Output caching subsystem stores whole pages in the
10
+ # filesystem to be served directly be the front web server
11
+ # (Lighttpd, Apache, etc) for optimal performance.
12
+ #
13
+ # Nitro promotes coding your application in such a way as to
14
+ # allow for output caching to the greatest extend.
15
+ #--
16
+ # gmosx, FIXME: Don't create excessive directories, use better
17
+ # rewrite rules to handle xxx.html files.
18
+ #++
10
19
 
11
20
  module Output
12
21
 
13
22
  def self.included(base) # :nodoc:
14
- super
15
23
  base.extend(ClassMethods)
16
24
  base.module_eval do
17
25
  cattr_accessor :output_cache_root, 'public'
@@ -45,9 +45,13 @@ class Cgi
45
45
  out.print(Cgi.response_headers(context))
46
46
 
47
47
  if context.out.is_a?(IO)
48
- while buf = context.out.read(4096)
49
- out.write(buf)
50
- end
48
+ begin
49
+ while buf = context.out.read(4096)
50
+ out.write(buf)
51
+ end
52
+ ensure
53
+ context.out.close
54
+ end
51
55
  else
52
56
  out.print(context.out)
53
57
  end
@@ -27,10 +27,8 @@ module Render
27
27
  Thread.new do
28
28
  begin
29
29
  yield
30
- rescue Object => ex
31
- p ex
32
30
  ensure
33
- w.close
31
+ w.close
34
32
  end
35
33
  end
36
34
  end
@@ -1,5 +1,3 @@
1
- require 'nano/kernel/singleton'
2
-
3
1
  require 'glue/template'
4
2
 
5
3
  require 'nitro/compiler/elements'
@@ -215,14 +213,17 @@ class Compiler
215
213
  code << "params = [];"
216
214
  end
217
215
  code << %{
218
- if context.query_string
219
- context.query_string.split(/[&;]/).each_with_index do |qs, i|
216
+ unless context.query_string.blank?
217
+ all_params = context.query_string.split(/[&;]/)
218
+ is_hash = all_params.first.index('=')
219
+ all_params.each_with_index do |qs, i|
220
220
  }
221
221
  # Don't pass more parameters than the action's arity.
222
222
  if param_count > 0
223
223
  code << "break unless i < #{param_count};"
224
224
  end
225
225
  code << %{
226
+ break if qs.index('=') and not is_hash
226
227
  params[i] = CGI.unescape(qs.split(/=/).last)
227
228
  end
228
229
  end
@@ -1,4 +1,4 @@
1
- require 'mega/orm_support'
1
+ require 'facet/ormsupport'
2
2
 
3
3
  module Nitro
4
4
 
@@ -1,8 +1,8 @@
1
1
  require 'rexml/document'
2
2
  require 'rexml/streamlistener'
3
3
 
4
- require 'mega/dictionary'
5
- require 'nano/string/blank'
4
+ require 'facet/dictionary'
5
+ require 'facet/string/blank'
6
6
 
7
7
  require 'glue/html'
8
8
 
@@ -1,4 +1,4 @@
1
- require 'nano/kernel/constant'
1
+ require 'facet/kernel/constant'
2
2
 
3
3
  require 'nitro/helper/javascript'
4
4
 
@@ -1,4 +1,4 @@
1
- require 'nano/kernel/assign_with'
1
+ require 'facet/kernel/assign_with'
2
2
 
3
3
  require 'nitro/cgi'
4
4
  require 'nitro/cgi/request'
@@ -55,7 +55,13 @@ class Context
55
55
  # end of the HTTP request handling code.
56
56
 
57
57
  def close
58
- @session.sync if @session
58
+ if @session
59
+ # Ugly hack: need to use AOP instead
60
+ if @session.has_key?(:FLASH)
61
+ @session[:FLASH].clean
62
+ end
63
+ @session.sync
64
+ end
59
65
  end
60
66
  alias_method :finish, :close
61
67
 
@@ -1,4 +1,4 @@
1
- require 'mega/annotation'
1
+ require 'facet/annotation'
2
2
 
3
3
  require 'glue/aspects'
4
4
  require 'glue/markup'
@@ -1,5 +1,3 @@
1
- require 'nano/kernel/singleton'
2
-
3
1
  require 'nitro/controller'
4
2
  require 'nitro/compiler'
5
3
  require 'nitro/routing'
@@ -1,8 +1,8 @@
1
- require 'nano/string/capitalized'
2
- require 'nano/string/camelize'
3
- require 'nano/string/underscore'
4
- require 'nano/dir/self/recurse'
5
- require 'mega/annotation'
1
+ require 'facet/string/capitalized'
2
+ require 'facet/string/camelize'
3
+ require 'facet/string/underscore'
4
+ require 'facet/dir/self/recurse'
5
+ require 'facet/annotation'
6
6
 
7
7
  require 'glue/flexob'
8
8
  require 'glue/configuration'
@@ -9,7 +9,7 @@ module Nitro
9
9
  def self.append_features(base)
10
10
  super
11
11
  base.before 'flash.discard'
12
- base.after 'flash.clean'
12
+ #base.after 'flash.clean'
13
13
  end
14
14
 
15
15
  # A Flash is a special hash object that lives in the session.
@@ -1,5 +1,5 @@
1
- require 'nano/kernel/constant'
2
- require 'nano/string/camelize'
1
+ require 'facet/kernel/constant'
2
+ require 'facet/string/camelize'
3
3
 
4
4
  require 'glue/attribute'
5
5
 
@@ -1,4 +1,4 @@
1
- require 'nano/inflect'
1
+ require 'facet/inflect'
2
2
 
3
3
  require 'nitro/helper/form/controls'
4
4
 
@@ -266,7 +266,8 @@ class HasManyControl < Control
266
266
  # to extend and customise the HasManyControl
267
267
 
268
268
  def all_items
269
- rel.target_class.all
269
+ return @all_items unless @all_items.nil?
270
+ @all_items = rel.target_class.all
270
271
  end
271
272
 
272
273
  def selected_items
@@ -1,4 +1,4 @@
1
- require 'nano/inflect'
1
+ require 'facet/inflect'
2
2
 
3
3
  module Nitro
4
4
 
@@ -1,4 +1,4 @@
1
- require 'mega/dictionary'
1
+ require 'facet/dictionary'
2
2
 
3
3
  require 'nitro/compiler/morphing'
4
4
 
@@ -1,4 +1,4 @@
1
- require 'nano/string/camelize'
1
+ require 'facet/inflect'
2
2
 
3
3
  require 'nitro/element'
4
4
 
@@ -120,12 +120,16 @@ class Pager
120
120
  end
121
121
  end
122
122
 
123
+ # Is the pager empty, ie has one page only?
124
+
123
125
  def empty?
124
- return @items.empty?
126
+ return @page_count < 1
125
127
  end
126
128
 
129
+ # The items count.
130
+
127
131
  def size
128
- return @items.size()
132
+ return @total_count
129
133
  end
130
134
 
131
135
  # Returns the range of the current page.
@@ -271,7 +275,7 @@ private
271
275
  when Array
272
276
  items = items.dup
273
277
  pager = Pager.new(request, per_page, items.size, pager_key)
274
- items = items.slice(pager.offset, pager.per_page)
278
+ items = items.slice(pager.offset, pager.per_page) || []
275
279
  return items, pager
276
280
 
277
281
  when Og::Collection
@@ -1,7 +1,7 @@
1
1
  require 'cgi'
2
2
  require 'rss/0.9'
3
3
 
4
- require 'nano/string/first_char'
4
+ require 'facet/string/first_char'
5
5
 
6
6
  require 'glue/markup'
7
7
 
@@ -2,7 +2,7 @@ require 'singleton'
2
2
  require 'sync'
3
3
  require 'stringio'
4
4
 
5
- require 'nano/string/blank'
5
+ require 'facet/string/blank'
6
6
 
7
7
  require 'glue/attribute'
8
8
  require 'glue/settings'
@@ -56,8 +56,13 @@ module Scaffolding
56
56
  @plural = options[:plural_name]
57
57
  @suffix = options[:suffix]
58
58
  @compiler = Compiler.new(@controller)
59
+
59
60
  @base = options[:base] || options[:mount] || options[:at]
60
- @base = @plural.dup if @base == true
61
+ if @base == true
62
+ @base = @plural.dup
63
+ elsif @base == :ROOT
64
+ @base = nil
65
+ end
61
66
  @base__ = "#{@base}__" if @base
62
67
  end
63
68
 
@@ -257,6 +262,16 @@ module Scaffolding
257
262
  # This method modifies both the controller and the
258
263
  # scaffolded Class.
259
264
  #
265
+ #
266
+ # === Options
267
+ #
268
+ # * base/mount : mountpoint for the action, defines a
269
+ # prefix for the scaffolded action.
270
+ # If mount => true, the prefix is the plural of the
271
+ # scaffolded class name.
272
+ # If mount => :ROOT or nil, the actions are mounted at the
273
+ # root of the controller.
274
+ #
260
275
  # === Example
261
276
  #
262
277
  # scaffold Article
@@ -278,6 +293,8 @@ module Scaffolding
278
293
  #--
279
294
  # This is the first phase of the scaffolding proccess,
280
295
  # scaffold targets are marked, and default options set.
296
+ #
297
+ # FIXME: Rethink the options, make :ROOT the default.
281
298
  #++
282
299
 
283
300
  def scaffold(klass, options = {})
@@ -301,7 +318,7 @@ module Scaffolding
301
318
 
302
319
  def compile_scaffolding_code
303
320
  # load scaffolding for all og classes if specified
304
-
321
+
305
322
  if scaffold_all?
306
323
  options = scaffold_all_options
307
324
  Og.manager.manageable_classes.each do |klass|
@@ -320,8 +337,13 @@ module Scaffolding
320
337
  end
321
338
 
322
339
  #--
323
- # set the options flag to trigger scaffolding of all classes in second phase
324
- # use exclude to ignore classes.... scaffold_all :exclude => [Product, Category]
340
+ # set the options flag to trigger scaffolding of all classes
341
+ # in second phase.
342
+ # use exclude to ignore classes:
343
+ # scaffold_all :exclude => [Product, Category]
344
+ #
345
+ # gmosx: I do NOT lke this, will remove this in a future
346
+ # version.
325
347
  #++
326
348
 
327
349
  def scaffold_all(options = {})