nitro 0.13.0 → 0.14.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 (64) hide show
  1. data/CHANGELOG +91 -1632
  2. data/INSTALL +44 -0
  3. data/README +1 -1
  4. data/Rakefile +3 -3
  5. data/doc/CHANGELOG.2 +1688 -0
  6. data/doc/RELEASES +84 -1
  7. data/examples/blog/cache/entriesadmin +12 -0
  8. data/examples/blog/conf/apache.conf.new +53 -0
  9. data/examples/blog/conf/lhttpd.conf +23 -180
  10. data/examples/blog/log/apache.error_log +271 -0
  11. data/examples/blog/log/rewrite_log +161 -0
  12. data/examples/blog/public/fcgi.rb +2 -0
  13. data/examples/blog/run.rb +4 -3
  14. data/examples/blog/src/controller.rb +10 -4
  15. data/examples/blog/src/views/index.xhtml +3 -0
  16. data/examples/blog/src/xsl/base.xsl +7 -0
  17. data/examples/no_xsl_blog/conf/lhttpd.conf +24 -181
  18. data/examples/tiny/conf/lhttpd.conf +24 -181
  19. data/examples/tiny/log/apache.error_log +24 -0
  20. data/examples/tiny/public/index.xhtml +0 -6
  21. data/examples/tiny/public/upload.xhtml +12 -14
  22. data/examples/wee_style/run.rb +2 -0
  23. data/examples/why_wiki/run.rb +2 -0
  24. data/lib/nitro.rb +2 -2
  25. data/lib/nitro/adapters/cgi.rb +36 -109
  26. data/lib/nitro/adapters/webrick.rb +76 -62
  27. data/lib/nitro/caching.rb +29 -0
  28. data/lib/nitro/caching/actions.rb +67 -0
  29. data/lib/nitro/caching/fragments.rb +72 -0
  30. data/lib/nitro/caching/invalidation.rb +51 -0
  31. data/lib/nitro/caching/output.rb +72 -0
  32. data/lib/nitro/caching/stores.rb +84 -0
  33. data/lib/nitro/controller.rb +3 -1
  34. data/lib/nitro/dispatcher.rb +0 -1
  35. data/lib/nitro/filters.rb +112 -55
  36. data/lib/nitro/mail.rb +6 -3
  37. data/lib/nitro/render.rb +27 -4
  38. data/lib/nitro/request.rb +13 -1
  39. data/test/nitro/tc_controller.rb +6 -4
  40. data/test/nitro/tc_filters.rb +111 -0
  41. metadata +19 -29
  42. data/examples/why_wiki/wiki.yml +0 -1
  43. data/vendor/README +0 -11
  44. data/vendor/binding_of_caller.rb +0 -81
  45. data/vendor/blankslate.rb +0 -53
  46. data/vendor/breakpoint.rb +0 -523
  47. data/vendor/breakpoint_client.rb +0 -196
  48. data/vendor/extensions/_base.rb +0 -153
  49. data/vendor/extensions/_template.rb +0 -36
  50. data/vendor/extensions/all.rb +0 -21
  51. data/vendor/extensions/array.rb +0 -68
  52. data/vendor/extensions/binding.rb +0 -224
  53. data/vendor/extensions/class.rb +0 -50
  54. data/vendor/extensions/continuation.rb +0 -71
  55. data/vendor/extensions/enumerable.rb +0 -250
  56. data/vendor/extensions/hash.rb +0 -23
  57. data/vendor/extensions/io.rb +0 -58
  58. data/vendor/extensions/kernel.rb +0 -42
  59. data/vendor/extensions/module.rb +0 -114
  60. data/vendor/extensions/numeric.rb +0 -230
  61. data/vendor/extensions/object.rb +0 -164
  62. data/vendor/extensions/ostruct.rb +0 -41
  63. data/vendor/extensions/string.rb +0 -316
  64. data/vendor/extensions/symbol.rb +0 -28
@@ -0,0 +1,84 @@
1
+ # * George Moschovitis <gm@navel.gr>
2
+ # (c) 2004-2005 Navel, all rights reserved.
3
+ # $Id: stores.rb 326 2005-03-28 11:07:17Z gmosx $
4
+
5
+ require 'fileutils'
6
+
7
+ require 'glue/hash'
8
+
9
+ module N
10
+
11
+ # Adds support for caching.
12
+
13
+ module Caching
14
+
15
+ # Cached fragments are stored in memory.
16
+
17
+ class MemoryStore < SafeHash
18
+
19
+ def read(name, options = {})
20
+ self[name]
21
+ end
22
+
23
+ def write(name, content = '', options = {})
24
+ self[name] = content
25
+ end
26
+
27
+ def delete(name, options = {})
28
+ self.delete(name)
29
+ end
30
+
31
+ end
32
+
33
+ # Cached fragments are stored as html files
34
+ # on the filesystem.
35
+
36
+ class FileStore
37
+ cattr_accessor :cache_root, 'cache'
38
+
39
+ def initialize(cache_root = @@cache_root)
40
+ @cache_root = FileStore.cache_root
41
+ end
42
+
43
+ def read(name, options = {})
44
+ begin
45
+ IO.read(path_for_name(name))
46
+ rescue
47
+ nil
48
+ end
49
+ end
50
+
51
+ def write(name, content = '', options = {})
52
+ begin
53
+ path = path_for_name(name)
54
+ dir = File.dirname(path)
55
+ FileUtils.makedirs(dir) unless File.exists?(dir)
56
+
57
+ File.open(path, 'w+') { |f| f.write(content) }
58
+ rescue
59
+ Logger.error "Could not save cached file '#{path}'"
60
+ end
61
+ end
62
+
63
+ def delete(name, options = {})
64
+ path = path_for_name(name)
65
+ File.delete(path) if File.exist?(path)
66
+ end
67
+
68
+ private
69
+
70
+ def path_for_name(name)
71
+ "#@cache_root/#{name}"
72
+ end
73
+
74
+ end
75
+
76
+ class DrbStrore
77
+ end
78
+
79
+ class MemcacheStore
80
+ end
81
+
82
+ end
83
+
84
+ end
@@ -5,6 +5,7 @@
5
5
  require 'nitro/render'
6
6
  require 'nitro/scaffold'
7
7
  require 'nitro/filters'
8
+ require 'nitro/caching'
8
9
 
9
10
  module N
10
11
 
@@ -78,6 +79,7 @@ class Controller
78
79
  include Render
79
80
  include Scaffolding
80
81
  include Filtering
82
+ include Caching
81
83
 
82
84
  # A hash containing metadata for the action
83
85
  # methods.
@@ -101,7 +103,7 @@ class Controller
101
103
 
102
104
  def inherited(subclass)
103
105
  subclass.class_eval %{
104
- DEF_FILE = caller[2].split(':').first
106
+ DEF_FILE = caller[2].split(':')[-2]
105
107
  }
106
108
  __old_inherited(subclass)
107
109
  end
@@ -162,7 +162,6 @@ class Dispatcher
162
162
 
163
163
  content_type = @apis[:api] || 'text/html'
164
164
 
165
- # return klass, "__#{api}__#{action}", base, content_type
166
165
  return klass, "__#{api}__#{action}", content_type
167
166
  end
168
167
  alias_method :split_path, :dispatch
data/lib/nitro/filters.rb CHANGED
@@ -1,11 +1,11 @@
1
1
  # * George Moschovitis <gm@navel.gr>
2
2
  # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: filters.rb 249 2005-02-04 14:03:00Z gmosx $
3
+ # $Id: filters.rb 326 2005-03-28 11:07:17Z gmosx $
4
4
 
5
5
  module N
6
6
 
7
- # Filtering functionality for renders/services. The design
8
- # and implementation is HEAVILY influenced by Rails.
7
+ # Filtering functionality for renders.
8
+ # The design and implementation is HEAVILY influenced by Rails.
9
9
  #
10
10
  # == Examples
11
11
  #
@@ -19,68 +19,108 @@ module N
19
19
  # filter
20
20
  # after
21
21
  #--
22
- # TODO:
23
- # implement inheritable filters.
22
+ # TODO: implement inheritable filters.
24
23
  #++
25
24
 
26
25
  module Filtering
27
26
 
28
- # Ruby is sometimes VERY surprising, the following trick is needed
29
- # to include singleton methods in other classes.
30
-
27
+ # Store the code and the metadata (options) for
28
+ # the a Filter.
29
+
30
+ Filter = Struct.new(:code, :options)
31
+
31
32
  def self.append_features(base)
32
- super; base.extend(ClassMethods)
33
+ super
34
+ base.extend(ClassMethods)
35
+ base.class_eval %{
36
+ @before_filters = []
37
+
38
+ def self.before_filters
39
+ @before_filters
40
+ end
41
+
42
+ def self.before_filters=(bf)
43
+ @before_filters = bf
44
+ end
45
+
46
+ @after_filters = []
47
+
48
+ def self.after_filters
49
+ @after_filters
50
+ end
51
+
52
+ def self.after_filters=(af)
53
+ @after_filters = af
54
+ end
55
+
56
+ def self.inherited(sub)
57
+ super
58
+ sub.before_filters = self.before_filters.dup
59
+ sub.after_filters = self.after_filters.dup
60
+ end
61
+ }
33
62
  end
34
63
 
35
64
  module ClassMethods
36
- # the filters to be evaluated before the method
37
- @@before_filters = []
38
-
39
- # the filters to be evaluated after the method
40
- @@after_filters = []
41
-
42
- #
43
- #
44
- def before_filters
45
- @@before_filters
46
- end
47
-
48
- #
49
- #
50
- def after_filters
51
- @@after_filters
52
- end
53
65
 
54
- #
66
+ # Prepend a filter to the before_filters collection.
55
67
 
56
- def prepend_before_filter(*filters, &block)
57
- filters << block if block_given?
58
- @@before_filters = filters + @@before_filters
68
+ def prepend_before_filter(*args, &block)
69
+ options = args.pop if args.last.is_a?(Hash)
70
+
71
+ if block_given?
72
+ filters = [ Filter.new(block, options) ]
73
+ else
74
+ filters = args.collect { |c| Filter.new(c, options) }
75
+ end
76
+
77
+ self.before_filters = filters + self.before_filters
59
78
  end
60
79
 
61
- #
80
+ # Append a filter to the before_filters collection.
62
81
 
63
- def append_before_filter(*filters, &block)
64
- filters << block if block_given?
65
- @@before_filters = @@before_filters + filters
82
+ def append_before_filter(*args, &block)
83
+ options = args.pop if args.last.is_a?(Hash)
84
+
85
+ if block_given?
86
+ filters = [ Filter.new(block, options) ]
87
+ else
88
+ filters = args.collect { |c| Filter.new(c, options) }
89
+ end
90
+
91
+ self.before_filters = self.before_filters + filters
66
92
  end
67
93
 
68
94
  # Alias for the most common case.
69
95
 
70
96
  alias :before_filter :prepend_before_filter
71
97
 
72
- #
98
+ # Prepend a filter to the after_filters collection.
73
99
 
74
- def prepend_after_filter(*filters, &block)
75
- filters << block if block_given?
76
- @@after_filters = filters + @@after_filters
100
+ def prepend_after_filter(*args, &block)
101
+ options = args.pop if args.last.is_a?(Hash)
102
+
103
+ if block_given?
104
+ filters = [ Filter.new(block, options) ]
105
+ else
106
+ filters = args.collect { |c| Filter.new(c, options) }
107
+ end
108
+
109
+ self.after_filters = filters + self.after_filters
77
110
  end
78
111
 
79
- #
112
+ # Append a filter to the after_filters collection.
80
113
 
81
- def append_after_filter(*filters, &block)
82
- filters << block if block_given?
83
- @@after_filters = @@after_filters + filters
114
+ def append_after_filter(*args, &block)
115
+ options = args.pop if args.last.is_a?(Hash)
116
+
117
+ if block_given?
118
+ filters = [ Filter.new(block, options) ]
119
+ else
120
+ filters = args.collect { |c| Filter.new(c, options) }
121
+ end
122
+
123
+ self.after_filters = self.after_filters + filters
84
124
  end
85
125
 
86
126
  # Alias for the most common case.
@@ -91,17 +131,19 @@ module Filtering
91
131
  # to the before and after methods. Both methods are prepended to
92
132
  # the respective lists.
93
133
 
94
- def prepend_arround_filter(*filters)
95
- filters = [filters].flatten
134
+ def prepend_arround_filter(*args)
135
+ options = args.pop if args.last.is_a?(Hash)
136
+
137
+ filters = [options].flatten
96
138
 
97
139
  for filter in filters
98
140
  if filter.respond_to?(:before)
99
- prepend_before_filter { |c| filter.before(c) }
141
+ prepend_before_filter(options) { |c| filter.before(c) }
100
142
  elsif filter.respond_to?(:filter)
101
143
  # consider 'filter' as synonym of before.
102
- prepend_before_filter { |c| filter.filter(c) }
144
+ prepend_before_filter(options) { |c| filter.filter(c) }
103
145
  end
104
- prepend_after_filter { |c| filter.after(c) } if filter.respond_to?(:after)
146
+ prepend_after_filter(options) { |c| filter.after(c) } if filter.respond_to?(:after)
105
147
  end
106
148
  end
107
149
 
@@ -109,31 +151,46 @@ module Filtering
109
151
  # to the before and after methods. Both methods are appended to
110
152
  # the respective lists.
111
153
 
112
- def append_arround_filter(*filters)
154
+ def append_arround_filter(*args)
155
+ options = args.pop if args.last.is_a?(Hash)
156
+
113
157
  filters = [filters].flatten
114
158
 
115
159
  for filter in filters
116
160
  if filter.respond_to?(:before)
117
- append_before_filter { |c| filter.before(c) }
161
+ append_before_filter(options) { |c| filter.before(c) }
118
162
  elsif filter.respond_to?(:filter)
119
163
  # consider 'filter' as synonym of before.
120
- append_before_filter { |c| filter.filter(c) }
164
+ append_before_filter(options) { |c| filter.filter(c) }
121
165
  end
122
- append_after_filter { |c| filter.after(c) } if filter.respond_to?(:after)
166
+ append_after_filter(options) { |c| filter.after(c) } if filter.respond_to?(:after)
123
167
  end
124
168
  end
125
169
 
126
170
  # Alias for the most common case.
127
171
  alias :filter :append_arround_filter
128
172
 
129
- #
173
+ # Generates the code to call the filters
130
174
 
131
- def gen_filters_call_code(filters)
175
+ def gen_filters_call_code(action, filters) # :nodoc:
132
176
  code = ""
133
177
 
134
- filters.each do |filter|
178
+ for filter in filters
179
+
180
+ if options = filter.options
181
+ if only = options[:only]
182
+ next unless [only].flatten.include?(action.to_sym)
183
+ elsif except = options[:except]
184
+ next if [except].flatten.include?(action.to_sym)
185
+ end
186
+ end
187
+
188
+ filter = filter.code
189
+
135
190
  if Symbol === filter
136
191
  code << "if #{filter} == false then return false end;"
192
+ elsif String === filter
193
+ code << "#{filter};"
137
194
  elsif filter.respond_to?('call') && (filter.arity == 1 || filter.arity == -1)
138
195
  code << 'if filter.call(self) == false then return false end;'
139
196
  elsif filter.is_a?(Module) and filter.instance_methods.size > 0
@@ -143,7 +200,7 @@ module Filtering
143
200
  elsif filter.respond_to?('filter')
144
201
  code << "if #{filter}.filter(self) == false then return false end"
145
202
  else
146
- raise 'Valid filters are either a symbol or a proc/method.'
203
+ raise 'Valid filters are either a symbol, a string or a proc/method.'
147
204
  end
148
205
  end
149
206
 
data/lib/nitro/mail.rb CHANGED
@@ -4,7 +4,7 @@
4
4
  #
5
5
  # * George Moschovitis <gm@navel.gr>
6
6
  # (c) 2004-2005 Navel, all rights reserved.
7
- # $Id: mail.rb 300 2005-03-16 13:23:10Z gmosx $
7
+ # $Id: mail.rb 323 2005-03-24 09:43:52Z gmosx $
8
8
 
9
9
  require 'net/smtp'
10
10
 
@@ -221,8 +221,11 @@ class Mailer < Mail
221
221
  mailer.body = render_body(method_name, mailer)
222
222
  end
223
223
 
224
- mail = create(mailer.from, mailer.to, mailer.subject, mailer.body, mailer.sent_on,
225
- mailer.headers, mailer.charset)
224
+ mail = create(
225
+ mailer.from, mailer.to, mailer.subject,
226
+ mailer.body, mailer.sent_on,
227
+ mailer.headers, mailer.charset
228
+ )
226
229
 
227
230
  mail.cc = mailer.cc if mailer.cc
228
231
  mail.bcc = mailer.bcc if mailer.bcc
data/lib/nitro/render.rb CHANGED
@@ -101,13 +101,15 @@ module Rendering
101
101
 
102
102
  code = %{
103
103
  def __#{api}__#{action}
104
+ old_action_name = @action_name
105
+ @action_name = '#{action}'
104
106
  }
105
107
 
106
108
  # call 'before' filter chain.
107
109
 
108
110
  if klass.respond_to?(:before_filters)
109
111
  code << %{
110
- #{klass.gen_filters_call_code(klass.before_filters)}
112
+ #{klass.gen_filters_call_code(action, klass.before_filters)}
111
113
  }
112
114
  end
113
115
 
@@ -152,11 +154,13 @@ module Rendering
152
154
 
153
155
  if klass.respond_to?(:after_filters)
154
156
  code << %{
155
- #{klass.gen_filters_call_code(klass.after_filters)}
157
+ #{klass.gen_filters_call_code(action, klass.after_filters)}
156
158
  }
157
159
  end
158
160
 
159
161
  code << %{
162
+ @action_name = old_action_name
163
+
160
164
  redirect_referer if @out.empty?
161
165
  end
162
166
  }
@@ -168,7 +172,9 @@ module Rendering
168
172
  end
169
173
  }
170
174
  end
171
-
175
+
176
+ # puts '---', code, '---' if action.to_s == 'index'
177
+
172
178
  klass.class_eval(code)
173
179
  end
174
180
 
@@ -201,6 +207,10 @@ module Render
201
207
 
202
208
  attr_accessor :rendering_errors
203
209
 
210
+ # The name of the currently executing action.
211
+
212
+ attr_accessor :action_name
213
+
204
214
  # The template root for this render.
205
215
 
206
216
  cattr_accessor :template_root
@@ -223,7 +233,6 @@ module Render
223
233
  def render(path)
224
234
  Logger.debug "Rendering '#{path}'." if $DBG
225
235
 
226
- # klass, action, template_root, ctype = @context.dispatcher.dispatch(path, @context)
227
236
  klass, action, content_type = @context.dispatcher.dispatch(path, @context)
228
237
 
229
238
  @context.content_type = content_type
@@ -250,6 +259,20 @@ module Render
250
259
  @out << '(error)'
251
260
  end
252
261
 
262
+ # Add some text to the output buffer.
263
+
264
+ def render_text(text)
265
+ @out << text
266
+ end
267
+
268
+ #--
269
+ # FIXME: do something better to stop the redirect.
270
+ #++
271
+
272
+ def render_nothing
273
+ @out = ' '
274
+ end
275
+
253
276
  private
254
277
 
255
278
  # Send a redirect response.