nitro 0.30.0 → 0.31.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/ProjectInfo +6 -6
- data/bin/nitro +100 -7
- data/doc/RELEASES +18 -0
- data/lib/glue/sweeper.rb +9 -5
- data/lib/nitro.rb +13 -13
- data/lib/nitro/adapter/console.rb +7 -0
- data/lib/nitro/adapter/mongrel.rb +34 -71
- data/lib/nitro/adapter/script.rb +71 -0
- data/lib/nitro/adapter/webrick.rb +0 -2
- data/lib/nitro/caching.rb +0 -1
- data/lib/nitro/caching/fragments.rb +2 -3
- data/lib/nitro/caching/output.rb +3 -4
- data/lib/nitro/cgi.rb +14 -0
- data/lib/nitro/cgi/request.rb +10 -9
- data/lib/nitro/cgi/sendfile.rb +45 -0
- data/lib/nitro/compiler.rb +1 -1
- data/lib/nitro/compiler/errors.rb +3 -3
- data/lib/nitro/context.rb +16 -1
- data/lib/nitro/controller.rb +60 -5
- data/lib/nitro/dispatcher.rb +2 -1
- data/lib/nitro/helper.rb +0 -2
- data/lib/nitro/helper/form/builder.rb +5 -1
- data/lib/nitro/helper/javascript.rb +1 -1
- data/lib/nitro/helper/pager.rb +19 -10
- data/lib/nitro/helper/table.rb +28 -3
- data/lib/nitro/helper/xhtml.rb +4 -3
- data/lib/nitro/part.rb +57 -2
- data/lib/nitro/render.rb +67 -28
- data/lib/nitro/router.rb +1 -0
- data/lib/nitro/scaffold.rb +141 -0
- data/lib/nitro/scaffolding.rb +17 -17
- data/lib/nitro/server/runner.rb +2 -9
- data/lib/nitro/session.rb +13 -5
- data/lib/nitro/test/testcase.rb +2 -0
- data/proto/run.rb +3 -1
- data/src/part/admin/controller.rb +2 -1
- data/src/part/admin/template/index.xhtml +2 -2
- data/test/nitro/tc_element.rb +13 -11
- data/test/nitro/tc_render.rb +1 -2
- metadata +186 -182
- data/bin/nitrogen +0 -5
- data/lib/nitro/helper/wee.rb +0 -57
data/lib/nitro/caching.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'fileutils'
|
2
2
|
|
3
3
|
require 'glue/configuration'
|
4
|
-
require 'glue/attribute'
|
5
4
|
require 'glue/cache/memory'
|
6
5
|
|
7
6
|
module Nitro
|
@@ -20,11 +19,11 @@ module Caching
|
|
20
19
|
setting :cache, :default => Glue::MemoryCache.new, :doc => 'The cache used to store the fragments'
|
21
20
|
|
22
21
|
def self.get(name, options = {})
|
23
|
-
return
|
22
|
+
return self.cache.get(name, options)
|
24
23
|
end
|
25
24
|
|
26
25
|
def self.put(name, content = nil, options = {})
|
27
|
-
|
26
|
+
self.cache.put(name, content, options)
|
28
27
|
return content
|
29
28
|
end
|
30
29
|
|
data/lib/nitro/caching/output.rb
CHANGED
@@ -6,6 +6,8 @@ module Nitro
|
|
6
6
|
|
7
7
|
module Caching
|
8
8
|
|
9
|
+
setting :output_cache_root, :default => 'public', :doc => 'The directory where cached pages are generated'
|
10
|
+
|
9
11
|
# The Output caching subsystem stores whole pages in the
|
10
12
|
# filesystem to be served directly be the front web server
|
11
13
|
# (Lighttpd, Apache, etc) for optimal performance.
|
@@ -22,9 +24,6 @@ module Caching
|
|
22
24
|
|
23
25
|
def self.included(base) # :nodoc:
|
24
26
|
base.extend(ClassMethods)
|
25
|
-
base.module_eval do
|
26
|
-
cattr_accessor :output_cache_root, 'public'
|
27
|
-
end
|
28
27
|
end
|
29
28
|
|
30
29
|
module ClassMethods
|
@@ -54,7 +53,7 @@ module Caching
|
|
54
53
|
filename = ((path.empty? || path == '/') ? 'index.html' : path.dup)
|
55
54
|
# filename.gsub!(/\/$/, '')
|
56
55
|
filename << '/index.html' unless (filename.split('/').last || filename).include? '.'
|
57
|
-
return output_cache_root + '/' + filename
|
56
|
+
return Caching.output_cache_root + '/' + filename
|
58
57
|
end
|
59
58
|
|
60
59
|
end
|
data/lib/nitro/cgi.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'cgi'
|
2
2
|
|
3
|
+
require 'stringio'
|
4
|
+
|
3
5
|
require 'glue/configuration'
|
4
6
|
require 'nitro/cgi/http'
|
5
7
|
|
@@ -21,10 +23,22 @@ class Cgi
|
|
21
23
|
|
22
24
|
# Process a CGI request. This is a general method reused by
|
23
25
|
# many adapters.
|
26
|
+
#--
|
27
|
+
# A CGI request is process-based so there is no need for Og
|
28
|
+
# connection cleanup.
|
29
|
+
#++
|
24
30
|
|
25
31
|
def self.process(server, cgi, inp, out)
|
26
32
|
context = Context.new(server)
|
27
33
|
|
34
|
+
unless inp.respond_to?(:rewind)
|
35
|
+
# The module Request#raw_body requires a rewind method,
|
36
|
+
# so if the input stream doesn't have one, *cough* FCgi,
|
37
|
+
# we convert it to a StringIO.
|
38
|
+
|
39
|
+
inp = StringIO.new(inp.read.to_s) # if read returns nil, to_s makes it ""
|
40
|
+
end
|
41
|
+
|
28
42
|
context.in = inp
|
29
43
|
context.headers = cgi.env
|
30
44
|
|
data/lib/nitro/cgi/request.rb
CHANGED
@@ -64,7 +64,7 @@ module Request
|
|
64
64
|
# www.nitroproject.org: request.domain # => 'nitroproject.org'
|
65
65
|
# www.nitroproject.co.uk: request.domain(2) # => 'nitroproject.co.uk'
|
66
66
|
|
67
|
-
def domain
|
67
|
+
def domain tld_length = 1
|
68
68
|
host.split('.').last(1 + tld_length).join('.')
|
69
69
|
end
|
70
70
|
|
@@ -74,7 +74,7 @@ module Request
|
|
74
74
|
#
|
75
75
|
# my.name.nitroproject.org: request.subdomains # => ['my', 'name']
|
76
76
|
|
77
|
-
def subdomains
|
77
|
+
def subdomains tld_length = 1
|
78
78
|
parts = host.split('.')
|
79
79
|
parts[0..-(tld_length+2)]
|
80
80
|
end
|
@@ -104,7 +104,7 @@ module Request
|
|
104
104
|
# if request.get?
|
105
105
|
|
106
106
|
def method
|
107
|
-
@headers['REQUEST_METHOD'].downcase.
|
107
|
+
@headers['REQUEST_METHOD'].downcase.to_sym
|
108
108
|
end
|
109
109
|
|
110
110
|
#--
|
@@ -176,6 +176,7 @@ module Request
|
|
176
176
|
def referer
|
177
177
|
return @headers['HTTP_REFERER'] || '/'
|
178
178
|
end
|
179
|
+
alias referrer referer
|
179
180
|
|
180
181
|
# The content_length
|
181
182
|
|
@@ -242,19 +243,19 @@ module Request
|
|
242
243
|
|
243
244
|
# Lookup a query parameter.
|
244
245
|
|
245
|
-
def []
|
246
|
+
def [] param
|
246
247
|
@params[param]
|
247
248
|
end
|
248
249
|
|
249
250
|
# Set a query parameter.
|
250
251
|
|
251
|
-
def []=
|
252
|
+
def []= param, value
|
252
253
|
@params[param] = value
|
253
254
|
end
|
254
255
|
|
255
256
|
# Check if a boolean param (checkbox) is true.
|
256
257
|
|
257
|
-
def true?
|
258
|
+
def true? param
|
258
259
|
@params[param] == 'on'
|
259
260
|
end
|
260
261
|
alias_method :enabled?, :true?
|
@@ -262,19 +263,19 @@ module Request
|
|
262
263
|
|
263
264
|
# Check if a boolean param (checkbox) is false.
|
264
265
|
|
265
|
-
def false?
|
266
|
+
def false? param
|
266
267
|
!true?(param)
|
267
268
|
end
|
268
269
|
|
269
270
|
# Fetch a parameter with default value.
|
270
271
|
|
271
|
-
def fetch
|
272
|
+
def fetch param, default = nil
|
272
273
|
@params.fetch(param, default)
|
273
274
|
end
|
274
275
|
|
275
276
|
# Check if a param is available.
|
276
277
|
|
277
|
-
def has_key?
|
278
|
+
def has_key? key
|
278
279
|
@params.has_key?(key)
|
279
280
|
end
|
280
281
|
alias_method :has_param?, :has_key?
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'nitro/render'
|
2
|
+
|
3
|
+
module Nitro
|
4
|
+
|
5
|
+
module Render
|
6
|
+
|
7
|
+
# Send a file download to the client.
|
8
|
+
#
|
9
|
+
# Like render and redirect, the action is exited upon calling
|
10
|
+
#
|
11
|
+
# [+fname+] That name of the file
|
12
|
+
# [+path+] Specifying true mean fname contains the full path.
|
13
|
+
# The default, false, uses Server.public_root as the path.
|
14
|
+
#
|
15
|
+
# [+return+] true on success, false on failure
|
16
|
+
#
|
17
|
+
# === Examples
|
18
|
+
#
|
19
|
+
# require 'nitro/cgi/sendfile'
|
20
|
+
# class MyController < Nitro:Controller
|
21
|
+
# def download(fname)
|
22
|
+
# sendfile(fname)
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# class MyController < Nitro:Controller
|
27
|
+
# def download()
|
28
|
+
# sendfile('/etc/password', true)
|
29
|
+
# end
|
30
|
+
# end
|
31
|
+
|
32
|
+
def sendfile(fname=nil, fullpath=false)
|
33
|
+
fname = fullpath ? fname : "#{Server.public_root}/#{fname}"
|
34
|
+
f = File.open(fname, "rb")
|
35
|
+
@context.response_headers["Cache-control"] = 'private'
|
36
|
+
@context.response_headers["Content-Length"] = "#{File.size?(f) || 0}"
|
37
|
+
@context.response_headers["Content-Type"] = 'application/force-download'
|
38
|
+
@context.out = f
|
39
|
+
raise RenderExit
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
data/lib/nitro/compiler.rb
CHANGED
@@ -258,7 +258,7 @@ class Compiler
|
|
258
258
|
end
|
259
259
|
|
260
260
|
# Concatenate some extracted parameters.
|
261
|
-
params.concat(context.params.values)
|
261
|
+
# params.concat(context.params.values)
|
262
262
|
|
263
263
|
# Fill the array with nils for the missing params.
|
264
264
|
(#{param_count} - params.size).times { params << nil }
|
@@ -10,7 +10,7 @@ require 'facet/ormsupport'
|
|
10
10
|
# or something.
|
11
11
|
#++
|
12
12
|
|
13
|
-
class Exception
|
13
|
+
class Exception # :nodoc: all
|
14
14
|
|
15
15
|
# Radius of the source code to display arround the error line.
|
16
16
|
|
@@ -45,7 +45,7 @@ class Exception
|
|
45
45
|
source = File.read(file)
|
46
46
|
|
47
47
|
if file =~ /\.xhtml$/
|
48
|
-
source = Compiler.new.transform_template(source)
|
48
|
+
source = Compiler.new(Nitro::Controller).transform_template(:action, source)
|
49
49
|
no -= 2
|
50
50
|
end
|
51
51
|
|
@@ -105,7 +105,7 @@ class Exception
|
|
105
105
|
|
106
106
|
def source_for_backtrace(indent = 0)
|
107
107
|
backtrace.inject([]) do |sources, step|
|
108
|
-
sources << source_extract(indent
|
108
|
+
sources << source_extract(step, indent)
|
109
109
|
end
|
110
110
|
end
|
111
111
|
|
data/lib/nitro/context.rb
CHANGED
@@ -63,6 +63,11 @@ class Context
|
|
63
63
|
# initialize the output buffer.
|
64
64
|
|
65
65
|
@out ||= OutputBuffer.new
|
66
|
+
|
67
|
+
# Store this instance in a thread local variable for easy
|
68
|
+
# access.
|
69
|
+
|
70
|
+
Thread.current[:CURRENT_CONTEXT] = self
|
66
71
|
end
|
67
72
|
|
68
73
|
|
@@ -162,7 +167,17 @@ class Context
|
|
162
167
|
alias_method :is_top?, :is_top_level?
|
163
168
|
alias_method :in_top_level?, :is_top_level?
|
164
169
|
alias_method :top_level?, :is_top_level?
|
165
|
-
|
170
|
+
|
171
|
+
class << self
|
172
|
+
|
173
|
+
# Returns the context for the current thread.
|
174
|
+
|
175
|
+
def current
|
176
|
+
Thread.current[:CURRENT_CONTEXT]
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
180
|
+
|
166
181
|
end
|
167
182
|
|
168
183
|
end
|
data/lib/nitro/controller.rb
CHANGED
@@ -46,6 +46,22 @@ module Publishable
|
|
46
46
|
include ::Aspects
|
47
47
|
include Flashing
|
48
48
|
include Helpers
|
49
|
+
|
50
|
+
# The collection of 'models' ie classes that are linked
|
51
|
+
# to this Publishable/Controller.
|
52
|
+
|
53
|
+
ann :self, :models => []
|
54
|
+
|
55
|
+
# This is a helper that 'links' one or more classes to this
|
56
|
+
# controller. In practice it annotates each class with the
|
57
|
+
# controller and stores the controller's list of 'models'.
|
58
|
+
|
59
|
+
def self.model *classes
|
60
|
+
for c in classes
|
61
|
+
c.ann :self, :controller => self
|
62
|
+
self.ann.self.models! << c
|
63
|
+
end
|
64
|
+
end
|
49
65
|
end
|
50
66
|
|
51
67
|
# Aliases an action
|
@@ -171,7 +187,7 @@ private
|
|
171
187
|
|
172
188
|
# Cookie helpers.
|
173
189
|
#--
|
174
|
-
# TODO: move elsewhere.
|
190
|
+
# TODO: move elsewhere, probably to a default helper.
|
175
191
|
#++
|
176
192
|
|
177
193
|
def cookies
|
@@ -207,13 +223,34 @@ private
|
|
207
223
|
# encode_url ForaController, :post, :title, 'Hello', :body, 'World'
|
208
224
|
# encode_url :post, :title, 'Hello', :body, 'World' # => implies controller == self
|
209
225
|
# encode_url :kick, :oid, 4
|
226
|
+
# encode_url article # => article.to_href
|
227
|
+
#
|
228
|
+
# Alternatively you can pass options with a hash:
|
229
|
+
#
|
230
|
+
# encode_url :controller => ForaController, :action => :delete, :params => { :title => 'Hello' }
|
231
|
+
# encode_url :action => :delete
|
210
232
|
#--
|
211
233
|
# FIXME: better implementation? optimize this?
|
212
234
|
# TODO: move elsewhere.
|
213
235
|
#++
|
214
236
|
|
215
|
-
def encode_url
|
216
|
-
|
237
|
+
def encode_url *args
|
238
|
+
f = args.first
|
239
|
+
|
240
|
+
# A standard url as string, return as is.
|
241
|
+
|
242
|
+
if f.is_a? String
|
243
|
+
return f
|
244
|
+
end
|
245
|
+
|
246
|
+
# If the passed param is an object that responds to :to_href
|
247
|
+
# returns the url to this object.
|
248
|
+
|
249
|
+
if f.respond_to? :to_href
|
250
|
+
return args.first.to_href
|
251
|
+
end
|
252
|
+
|
253
|
+
if f.is_a? Symbol
|
217
254
|
# no controller passed, imply controller == self!
|
218
255
|
args.unshift(self.class)
|
219
256
|
end
|
@@ -278,10 +315,10 @@ class Controller
|
|
278
315
|
|
279
316
|
# This callback is called after the Controller is mounted.
|
280
317
|
|
281
|
-
def self.mounted
|
318
|
+
def self.mounted path
|
282
319
|
# Resolve aspects.
|
283
320
|
|
284
|
-
|
321
|
+
Aspects.include_advice_modules(self)
|
285
322
|
|
286
323
|
# The scaffolding code is compiled after the mount, so
|
287
324
|
# that template roots are finalized.
|
@@ -289,6 +326,24 @@ class Controller
|
|
289
326
|
compile_scaffolding_code()
|
290
327
|
end
|
291
328
|
|
329
|
+
# Returns the current controller from the context thread local
|
330
|
+
# variable.
|
331
|
+
|
332
|
+
def self.current
|
333
|
+
Thread.current[:CURRENT_CONTROLLER]
|
334
|
+
end
|
335
|
+
|
336
|
+
#--
|
337
|
+
# Replaces the current controller (helper for render).
|
338
|
+
# This is an internal method.
|
339
|
+
#++
|
340
|
+
|
341
|
+
def self.replace_current controller # :nodoc:
|
342
|
+
old = Thread.current[:CURRENT_CONTROLLER]
|
343
|
+
Thread.current[:CURRENT_CONTROLLER] = controller
|
344
|
+
return old
|
345
|
+
end
|
346
|
+
|
292
347
|
end
|
293
348
|
|
294
349
|
end
|
data/lib/nitro/dispatcher.rb
CHANGED
@@ -128,7 +128,7 @@ class Dispatcher
|
|
128
128
|
for m in c.action_methods
|
129
129
|
m = m.to_sym
|
130
130
|
if route = c.ann(m).route and (!route.nil?)
|
131
|
-
|
131
|
+
add_rule(route.first, :controller => c, :action => m, :params => route.last)
|
132
132
|
end
|
133
133
|
end
|
134
134
|
end
|
@@ -168,6 +168,7 @@ class Dispatcher
|
|
168
168
|
return klass, "#{action}_action", klass.mount_path
|
169
169
|
end
|
170
170
|
|
171
|
+
path = path.sub(/#{Router.strip_path}/, '') if Router.strip_path
|
171
172
|
parts = path.split('/')
|
172
173
|
parts.shift # get rid of the leading '/'.
|
173
174
|
|
data/lib/nitro/helper.rb
CHANGED
@@ -90,6 +90,10 @@ module FormHelper
|
|
90
90
|
# for this form. If you pass a class an empty object is
|
91
91
|
# instantiated.
|
92
92
|
#
|
93
|
+
# * :action = The action of this form. The parameter is
|
94
|
+
# passed through the R operator (encode_url) to support
|
95
|
+
# advanced url encoding.
|
96
|
+
#
|
93
97
|
# === Example
|
94
98
|
#
|
95
99
|
# #{form(:object => @owner, :action => :save_profile) do |f|
|
@@ -120,7 +124,7 @@ module FormHelper
|
|
120
124
|
b = FormXmlBuilder.new('', options)
|
121
125
|
|
122
126
|
b << '<form'
|
123
|
-
b << %| action="#{options[:action]}"| if options[:action]
|
127
|
+
b << %| action="#{R options[:action]}"| if options[:action]
|
124
128
|
b << %| method="#{options[:method]}"| if options[:method]
|
125
129
|
b << %| enctype="#{options[:enctype]}"| if options[:enctype]
|
126
130
|
b << '>'
|