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.
- data/CHANGELOG +91 -1632
- data/INSTALL +44 -0
- data/README +1 -1
- data/Rakefile +3 -3
- data/doc/CHANGELOG.2 +1688 -0
- data/doc/RELEASES +84 -1
- data/examples/blog/cache/entriesadmin +12 -0
- data/examples/blog/conf/apache.conf.new +53 -0
- data/examples/blog/conf/lhttpd.conf +23 -180
- data/examples/blog/log/apache.error_log +271 -0
- data/examples/blog/log/rewrite_log +161 -0
- data/examples/blog/public/fcgi.rb +2 -0
- data/examples/blog/run.rb +4 -3
- data/examples/blog/src/controller.rb +10 -4
- data/examples/blog/src/views/index.xhtml +3 -0
- data/examples/blog/src/xsl/base.xsl +7 -0
- data/examples/no_xsl_blog/conf/lhttpd.conf +24 -181
- data/examples/tiny/conf/lhttpd.conf +24 -181
- data/examples/tiny/log/apache.error_log +24 -0
- data/examples/tiny/public/index.xhtml +0 -6
- data/examples/tiny/public/upload.xhtml +12 -14
- data/examples/wee_style/run.rb +2 -0
- data/examples/why_wiki/run.rb +2 -0
- data/lib/nitro.rb +2 -2
- data/lib/nitro/adapters/cgi.rb +36 -109
- data/lib/nitro/adapters/webrick.rb +76 -62
- data/lib/nitro/caching.rb +29 -0
- data/lib/nitro/caching/actions.rb +67 -0
- data/lib/nitro/caching/fragments.rb +72 -0
- data/lib/nitro/caching/invalidation.rb +51 -0
- data/lib/nitro/caching/output.rb +72 -0
- data/lib/nitro/caching/stores.rb +84 -0
- data/lib/nitro/controller.rb +3 -1
- data/lib/nitro/dispatcher.rb +0 -1
- data/lib/nitro/filters.rb +112 -55
- data/lib/nitro/mail.rb +6 -3
- data/lib/nitro/render.rb +27 -4
- data/lib/nitro/request.rb +13 -1
- data/test/nitro/tc_controller.rb +6 -4
- data/test/nitro/tc_filters.rb +111 -0
- metadata +19 -29
- data/examples/why_wiki/wiki.yml +0 -1
- data/vendor/README +0 -11
- data/vendor/binding_of_caller.rb +0 -81
- data/vendor/blankslate.rb +0 -53
- data/vendor/breakpoint.rb +0 -523
- data/vendor/breakpoint_client.rb +0 -196
- data/vendor/extensions/_base.rb +0 -153
- data/vendor/extensions/_template.rb +0 -36
- data/vendor/extensions/all.rb +0 -21
- data/vendor/extensions/array.rb +0 -68
- data/vendor/extensions/binding.rb +0 -224
- data/vendor/extensions/class.rb +0 -50
- data/vendor/extensions/continuation.rb +0 -71
- data/vendor/extensions/enumerable.rb +0 -250
- data/vendor/extensions/hash.rb +0 -23
- data/vendor/extensions/io.rb +0 -58
- data/vendor/extensions/kernel.rb +0 -42
- data/vendor/extensions/module.rb +0 -114
- data/vendor/extensions/numeric.rb +0 -230
- data/vendor/extensions/object.rb +0 -164
- data/vendor/extensions/ostruct.rb +0 -41
- data/vendor/extensions/string.rb +0 -316
- 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
|
data/lib/nitro/controller.rb
CHANGED
@@ -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(':')
|
106
|
+
DEF_FILE = caller[2].split(':')[-2]
|
105
107
|
}
|
106
108
|
__old_inherited(subclass)
|
107
109
|
end
|
data/lib/nitro/dispatcher.rb
CHANGED
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
|
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
|
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
|
-
#
|
29
|
-
#
|
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
|
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(*
|
57
|
-
|
58
|
-
|
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(*
|
64
|
-
|
65
|
-
|
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(*
|
75
|
-
|
76
|
-
|
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(*
|
82
|
-
|
83
|
-
|
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(*
|
95
|
-
|
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(*
|
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
|
-
|
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
|
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(
|
225
|
-
|
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.
|