cuca 0.03 → 0.04
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +39 -0
- data/application_skeleton/conf/config.rb +24 -5
- data/application_skeleton/public/dispatch.cgi +2 -15
- data/application_skeleton/public/dispatch.fcgi +4 -15
- data/lib/cuca.rb +5 -1
- data/lib/cuca/app.rb +97 -170
- data/lib/cuca/cgi_emu.rb +9 -0
- data/lib/cuca/cgi_fix.rb +10 -0
- data/lib/cuca/config.rb +67 -0
- data/lib/cuca/const.rb +1 -1
- data/lib/cuca/controller.rb +67 -26
- data/lib/cuca/layout.rb +1 -0
- data/lib/cuca/session.rb +7 -3
- data/lib/cuca/sessionpage.rb +1 -0
- data/lib/cuca/stdlib/arform.rb +12 -1
- data/lib/cuca/stdlib/listwidget/dblist.rb +2 -1
- data/lib/cuca/stdlib/listwidget/list.rb +5 -4
- data/lib/cuca/test/helpers.rb +3 -1
- data/lib/cuca/urlmap-original.rb +324 -0
- data/lib/cuca/urlmap.rb +68 -13
- data/lib/cuca/urlmap2.rb +22 -0
- data/lib/cuca/widget.rb +6 -6
- data/tests/all.rb +8 -0
- data/tests/app.rb +37 -0
- data/tests/controller.rb +163 -0
- data/tests/generator_markaby.rb +123 -0
- data/tests/generator_view.rb +76 -0
- data/tests/mimetypes.rb +20 -0
- data/tests/test_app/README +1 -0
- data/tests/test_app/app/_views/test_template.rhtml +1 -0
- data/tests/test_app/app/agent/index.rb +0 -0
- data/tests/test_app/app/agent/list.rb +0 -0
- data/tests/test_app/app/user/__username/index.rb +0 -0
- data/tests/test_app/app/user/list.rb +0 -0
- data/tests/test_app/conf/config.rb +0 -0
- data/tests/test_app/conf/environment.rb +0 -0
- data/tests/test_app/log/messages +1 -0
- data/tests/urlmap.rb +96 -0
- data/tests/widget.rb +153 -0
- metadata +33 -4
data/lib/cuca/urlmap.rb
CHANGED
@@ -16,16 +16,21 @@ end
|
|
16
16
|
#
|
17
17
|
# URLMap is used internally to match a URL to a controller file.
|
18
18
|
# Call with ds = URLMap.new('/path/to/app', 'path/from/url')
|
19
|
+
# URLMap.new(base_path, url)
|
19
20
|
#
|
20
21
|
# You can then fetch the following values:
|
21
22
|
#
|
22
23
|
# * script - path to the controller file
|
24
|
+
# * url - unmodified URL as passed to initializer
|
23
25
|
# * assigns - hash with variable assigns from the url (magick prefixes)
|
24
26
|
# * subcall - name of subcall or nil if a normal call was made
|
25
27
|
# * action - Action name (Note: action.capitalize+"Controller" is your controller class name)
|
26
28
|
# * base_url - Base URL to the action (e.g.: /user/someone/show is -> /user/someone/)
|
29
|
+
# * base_path - Unmodified base_path
|
27
30
|
# * action_path - Path to the action script
|
28
31
|
# * action_path_full - Full path to action script
|
32
|
+
# * path_tree - an array of each directory on the way from /path/to/app to the script
|
33
|
+
# (to look for include_directories in - see Cuca::Config)
|
29
34
|
# * action_module - The module the action should be loaded into (to avoid name conflicts, depends on action_path)
|
30
35
|
#
|
31
36
|
#
|
@@ -58,14 +63,17 @@ end
|
|
58
63
|
# u.action_path => 'customer/southwind_lda/'
|
59
64
|
#
|
60
65
|
class URLMap
|
66
|
+
attr_reader :url # current url
|
61
67
|
attr_reader :assigns
|
62
68
|
attr_reader :script
|
63
69
|
attr_reader :subcall
|
64
70
|
attr_reader :base_url
|
71
|
+
attr_reader :base_path
|
65
72
|
attr_reader :action
|
66
73
|
attr_reader :action_path
|
67
74
|
attr_reader :action_path_full
|
68
75
|
attr_reader :action_module
|
76
|
+
attr_reader :path_tree
|
69
77
|
|
70
78
|
DEF_ACT = Cuca::App::config['magic_action_prefix'] || '__'
|
71
79
|
DEF_IDX = [ 'index', 'default' ]
|
@@ -102,9 +110,28 @@ class URLMap
|
|
102
110
|
end
|
103
111
|
end
|
104
112
|
|
113
|
+
|
114
|
+
# scan_dir will look within a realdirectory for an unparsed url 'file' and return
|
115
|
+
# it's real path
|
105
116
|
private
|
106
117
|
def scan_dir(base, file)
|
107
|
-
|
118
|
+
|
119
|
+
striped = "#{base}/#{file}"[@base_path.length..-1]
|
120
|
+
mount = Cuca::App.config['mount'] || {}
|
121
|
+
# $stderr.puts "SCAN DIR: #{striped}"
|
122
|
+
# $stderr.puts "MOUNTS: #{mount.inspect}"
|
123
|
+
# $stderr.puts "AGAINST: #{striped} #{mount.has_key?(striped).inspect}"
|
124
|
+
|
125
|
+
|
126
|
+
|
127
|
+
if mount["#{striped}/"] then
|
128
|
+
# $stderr.puts "Found mount point, returning: #{mount["#{striped}/"]}"
|
129
|
+
return mount["#{striped}/"]
|
130
|
+
end
|
131
|
+
|
132
|
+
if File.directory?("#{base}/#{file}") then
|
133
|
+
return file.empty? ? base : "#{base}/#{file}" # avoid returning double //
|
134
|
+
end
|
108
135
|
|
109
136
|
d = Dir["#{base}/#{DEF_ACT}*"].collect { |f| f.split('/').last }
|
110
137
|
|
@@ -112,12 +139,13 @@ class URLMap
|
|
112
139
|
|
113
140
|
# puts d.inspect
|
114
141
|
#
|
142
|
+
|
115
143
|
raise RoutingError.new("Multiple default actions defined in #{base}") if d.size > 1
|
116
144
|
raise RoutingError.new("Routing Error in #{base}") if d.empty?
|
117
145
|
|
118
146
|
|
119
|
-
@assigns[d[0][DEF_ACT.size..-1]] = file
|
120
|
-
d[0]
|
147
|
+
@assigns[d[0][DEF_ACT.size..-1]] = file
|
148
|
+
"#{base}/#{d[0]}"
|
121
149
|
end
|
122
150
|
|
123
151
|
|
@@ -125,12 +153,12 @@ class URLMap
|
|
125
153
|
def make_module(path)
|
126
154
|
const_name = "Appmod_#{path.gsub(/[\/\\]/, '_')}"
|
127
155
|
|
128
|
-
if Cuca::const_defined?(const_name.intern) then
|
129
|
-
return Cuca::const_get(const_name.intern)
|
156
|
+
if Cuca::Objects::const_defined?(const_name.intern) then
|
157
|
+
return Cuca::Objects::const_get(const_name.intern)
|
130
158
|
end
|
131
159
|
|
132
160
|
m = Module.new
|
133
|
-
Cuca::const_set(const_name.intern, m)
|
161
|
+
Cuca::Objects::const_set(const_name.intern, m)
|
134
162
|
return m
|
135
163
|
end
|
136
164
|
|
@@ -142,17 +170,22 @@ class URLMap
|
|
142
170
|
|
143
171
|
files << '' if @path_info[@path_info.size-1].chr == '/' # add empty element if we point to a directory
|
144
172
|
|
173
|
+
# files now contains something like:
|
174
|
+
# [users, show, martin, contacts]
|
175
|
+
|
145
176
|
# puts files.inspect
|
146
|
-
real_path = @base_path
|
147
|
-
|
177
|
+
real_path = @base_path.dup
|
178
|
+
|
148
179
|
# scan directory
|
149
180
|
files.each_index do |idx|
|
150
181
|
next if idx >= (files.size-1) # skip last element
|
151
182
|
r = scan_dir(real_path, files[idx])
|
152
183
|
raise RoutingError.new("Routing Error at #{real_path} - #{files[idx]}") if !r
|
153
|
-
|
184
|
+
@path_tree << r
|
185
|
+
real_path = r
|
154
186
|
end
|
155
187
|
|
188
|
+
@url = @path_info
|
156
189
|
@base_url = "#{files[0..-2].join('/')}/"
|
157
190
|
@action_path = real_path[@base_path.length..-1]
|
158
191
|
@action_path_full = real_path
|
@@ -164,8 +197,9 @@ class URLMap
|
|
164
197
|
raise RoutingError.new("Routing Error - script not found at #{real_path} - #{files.last}") if !r
|
165
198
|
|
166
199
|
real_path = "#{real_path}/#{r}"
|
167
|
-
|
168
|
-
@script
|
200
|
+
|
201
|
+
@script = File.expand_path(real_path)
|
202
|
+
# @path_tree = _tree(@base_path, @script)
|
169
203
|
self
|
170
204
|
end
|
171
205
|
|
@@ -217,13 +251,14 @@ class URLMap
|
|
217
251
|
|
218
252
|
def initialize(base_path, path_info, default_actions = ['index'])
|
219
253
|
@path_info = path_info
|
220
|
-
@base_path = base_path
|
254
|
+
@base_path = File.expand_path(base_path)
|
221
255
|
@script = ''
|
222
256
|
@subcall = nil
|
223
257
|
@default_actions = default_actions
|
224
258
|
@assigns = {}
|
225
259
|
@action = ''
|
226
260
|
@action_path = ''
|
261
|
+
@path_tree = [base_path]
|
227
262
|
scan
|
228
263
|
self
|
229
264
|
end
|
@@ -241,7 +276,7 @@ if __FILE__ == $0 then
|
|
241
276
|
require 'app'
|
242
277
|
|
243
278
|
BASE = '/home/bones/src/cuca/app'
|
244
|
-
URL = 'user/martin/'
|
279
|
+
URL = 'user/martin/somewhere/notexist/'
|
245
280
|
|
246
281
|
puts "Testing on '#{BASE}' - '#{URL}'"
|
247
282
|
|
@@ -266,6 +301,26 @@ require 'app'
|
|
266
301
|
puts "Action Path: #{ds.action_path}"
|
267
302
|
puts "Action Path Full: #{ds.action_path_full}"
|
268
303
|
puts "Action Module: #{ds.action_module.inspect}"
|
304
|
+
puts "Path tree: #{ds.path_tree.inspect}"
|
269
305
|
end
|
270
306
|
|
271
307
|
end
|
308
|
+
|
309
|
+
|
310
|
+
|
311
|
+
|
312
|
+
|
313
|
+
|
314
|
+
|
315
|
+
# URL: "/user/martin/show"
|
316
|
+
# DIR: "/user/__userid/show'
|
317
|
+
# MOUNT: "/user/__userid/" =>>> "/plugin/user" contains 'show'
|
318
|
+
# MOUNT: "/user/__userid/" =>>> "/plugin/user2" contains 'see'
|
319
|
+
|
320
|
+
|
321
|
+
|
322
|
+
|
323
|
+
|
324
|
+
|
325
|
+
|
326
|
+
|
data/lib/cuca/urlmap2.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
class URLMap2
|
4
|
+
|
5
|
+
|
6
|
+
def path2array(p)
|
7
|
+
p.split('/')
|
8
|
+
end
|
9
|
+
def array2path(a)
|
10
|
+
a.join('/')
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
def initialize(directory, options)
|
15
|
+
@app_path = options[:app_path] || raise ArgumentError.new("app_path required")
|
16
|
+
@mounts = options[:mounts] || []
|
17
|
+
@url = options[:url] || raise ArgumentError.new("url required")
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
end
|
data/lib/cuca/widget.rb
CHANGED
@@ -74,12 +74,12 @@ class Widget
|
|
74
74
|
|
75
75
|
# An accessor to the global cgi variables
|
76
76
|
def cgi
|
77
|
-
$cgi
|
77
|
+
$app.cgi
|
78
78
|
end
|
79
79
|
|
80
80
|
# An accessor to the global logger variables
|
81
81
|
def log
|
82
|
-
$logger
|
82
|
+
$app.logger
|
83
83
|
end
|
84
84
|
|
85
85
|
# An accessor to the Cuca::app object
|
@@ -91,22 +91,22 @@ class Widget
|
|
91
91
|
# an accessor to cgi.parameters variables. This is NOT params from the CGI class
|
92
92
|
# (see cgi_fix)
|
93
93
|
def params
|
94
|
-
$cgi.parameters
|
94
|
+
$app.cgi.parameters
|
95
95
|
end
|
96
96
|
|
97
97
|
# accessor to cgi query parameters (http GET)
|
98
98
|
def query_parameters
|
99
|
-
$cgi.query_parameters
|
99
|
+
$app.cgi.query_parameters
|
100
100
|
end
|
101
101
|
|
102
102
|
# accessor to the cgi request parameters (http POST)
|
103
103
|
def request_parameters
|
104
|
-
$cgi.request_parameters
|
104
|
+
$app.cgi.request_parameters
|
105
105
|
end
|
106
106
|
|
107
107
|
# an accessor to request_method
|
108
108
|
def request_method
|
109
|
-
return $cgi.request_method
|
109
|
+
return $app.cgi.request_method
|
110
110
|
end
|
111
111
|
|
112
112
|
# Escape a string to use with URL etc..
|
data/tests/all.rb
ADDED
data/tests/app.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
$: << File.expand_path(File.dirname(__FILE__) + '/../lib')
|
4
|
+
|
5
|
+
$cuca_path = File.expand_path("#{File.dirname(__FILE__)}/test_app")
|
6
|
+
require 'cuca'
|
7
|
+
require 'cuca/urlmap'
|
8
|
+
require 'cuca/cgi_emu'
|
9
|
+
|
10
|
+
|
11
|
+
class TestApp < Test::Unit::TestCase
|
12
|
+
|
13
|
+
def test_basic
|
14
|
+
app = Cuca::App.new
|
15
|
+
assert app.app_path
|
16
|
+
assert app.public_path
|
17
|
+
assert app.log_path
|
18
|
+
assert app.logger.instance_of?(Logger)
|
19
|
+
assert_equal $app.object_id, app.object_id
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_configure
|
23
|
+
Cuca::App.configure do |conf|
|
24
|
+
conf.test_var = 'test'
|
25
|
+
end
|
26
|
+
assert_equal 'test', Cuca::App.config['test_var']
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_support_files_loading
|
30
|
+
app = Cuca::App.new
|
31
|
+
um = Cuca::URLMap.new("#{$cuca_path}/app/", "/user/list.rb")
|
32
|
+
app.load_support_files(um)
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
|
37
|
+
end
|
data/tests/controller.rb
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
$: << File.expand_path(File.dirname(__FILE__) + '/../lib')
|
4
|
+
|
5
|
+
$cuca_path = File.expand_path("#{File.dirname(__FILE__)}/test_app")
|
6
|
+
require 'cuca'
|
7
|
+
require 'cuca/urlmap'
|
8
|
+
|
9
|
+
class TestAController < Cuca::Controller
|
10
|
+
def get
|
11
|
+
content << 'GET'
|
12
|
+
end
|
13
|
+
def post
|
14
|
+
content << 'POST'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
class TestBController < Cuca::Controller
|
18
|
+
def run
|
19
|
+
content << 'RUN'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# test layout - will just put brackets around content
|
24
|
+
class TestLayout < Cuca::Layout
|
25
|
+
def output
|
26
|
+
@_content = "(#{@content_for_layout})"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# A Controller that defines a layout
|
31
|
+
class LayoutController < Cuca::Controller
|
32
|
+
layout 'test'
|
33
|
+
|
34
|
+
def run
|
35
|
+
content << "LAYOUT"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# should produce: "(zero-one-two-three-FILTER-aone-atwo)"
|
40
|
+
class FilterController < Cuca::Controller
|
41
|
+
priority_before_filter 'filter_pri'
|
42
|
+
before_filter 'filter_three', 30
|
43
|
+
before_filter 'filter_one', 1
|
44
|
+
before_filter 'filter_two', 10
|
45
|
+
|
46
|
+
priority_after_filter 'afilter_pri'
|
47
|
+
after_filter 'afilter_one', 10
|
48
|
+
after_filter 'afilter_two', 20
|
49
|
+
|
50
|
+
def run
|
51
|
+
content << "(#{@filter.join('-')}-FILTER"
|
52
|
+
end
|
53
|
+
|
54
|
+
def filter_pri
|
55
|
+
@filter = ['zero']
|
56
|
+
end
|
57
|
+
|
58
|
+
def afilter_pri
|
59
|
+
@_content << ')'
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
def filter_one
|
64
|
+
@filter << 'one'
|
65
|
+
end
|
66
|
+
|
67
|
+
def filter_two
|
68
|
+
@filter << 'two'
|
69
|
+
end
|
70
|
+
|
71
|
+
def filter_three
|
72
|
+
@filter << 'three'
|
73
|
+
end
|
74
|
+
|
75
|
+
def afilter_one
|
76
|
+
@_content << '-aone'
|
77
|
+
end
|
78
|
+
|
79
|
+
def afilter_two
|
80
|
+
@_content << '-atwo'
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
# this defines a filter that doesn't exist, raises ApplicationException
|
86
|
+
class BadFilterController < Cuca::Controller
|
87
|
+
before_filter 'notexist'
|
88
|
+
end
|
89
|
+
|
90
|
+
class ReturnErrorController < Cuca::Controller
|
91
|
+
def run
|
92
|
+
http_status 'SERVER_ERROR'
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
class ReturnOtherMimeController < Cuca::Controller
|
97
|
+
def run
|
98
|
+
mime_type 'text/plain'
|
99
|
+
@_content = 'test text'
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
class ControllerTests < Test::Unit::TestCase
|
105
|
+
|
106
|
+
def test_basic
|
107
|
+
c = Cuca::Controller.new
|
108
|
+
assert c.to_s == ''
|
109
|
+
|
110
|
+
a = TestAController.new
|
111
|
+
a._do('get')
|
112
|
+
assert_equal 'GET', a.to_s
|
113
|
+
a = TestAController.new
|
114
|
+
a._do('post')
|
115
|
+
assert_equal 'POST', a.to_s
|
116
|
+
|
117
|
+
b = TestBController.new
|
118
|
+
b._do('run')
|
119
|
+
assert_equal 'RUN', b.to_s
|
120
|
+
assert_equal "OK", b.http_status
|
121
|
+
assert_equal "text/html", b.mime_type
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_layout
|
125
|
+
l = LayoutController.new
|
126
|
+
l._do('run')
|
127
|
+
assert_equal '(LAYOUT)', l.to_s
|
128
|
+
assert_equal "OK", l.http_status
|
129
|
+
assert_equal "text/html", l.mime_type
|
130
|
+
end
|
131
|
+
|
132
|
+
|
133
|
+
def test_filters
|
134
|
+
f = FilterController.new
|
135
|
+
f.run_before_filters
|
136
|
+
f._do('run')
|
137
|
+
f.run_after_filters
|
138
|
+
assert_equal "(zero-one-two-three-FILTER-aone-atwo)", f.to_s
|
139
|
+
assert_equal "OK", f.http_status
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_badfilter
|
143
|
+
f = BadFilterController.new
|
144
|
+
assert_raise Cuca::ApplicationException do
|
145
|
+
f.run_before_filters
|
146
|
+
end
|
147
|
+
assert_equal "SERVER_ERROR", f.http_status
|
148
|
+
end
|
149
|
+
|
150
|
+
def test_http_status
|
151
|
+
c = ReturnErrorController.new
|
152
|
+
c._do('run')
|
153
|
+
assert_equal c.http_status, 'SERVER_ERROR'
|
154
|
+
end
|
155
|
+
|
156
|
+
def test_mime_type
|
157
|
+
c = ReturnOtherMimeController.new
|
158
|
+
c._do('run')
|
159
|
+
assert_equal c.mime_type, 'text/plain'
|
160
|
+
end
|
161
|
+
|
162
|
+
|
163
|
+
end
|