cuca 0.03 → 0.04
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 +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
|