cuca 0.04 → 0.05
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 +11 -2
- data/application_skeleton/app/index.rb +1 -1
- data/application_skeleton/conf/config.rb +5 -5
- data/lib/cuca.rb +22 -14
- data/lib/cuca/app.rb +1 -1
- data/lib/cuca/const.rb +1 -1
- data/lib/cuca/controller.rb +3 -4
- data/lib/cuca/generator/markaby.rb +18 -8
- data/lib/cuca/generator/view.rb +19 -13
- data/lib/cuca/session.rb +2 -0
- data/lib/cuca/stdlib/arform.rb +65 -3
- data/lib/cuca/stdlib/form.rb +17 -4
- data/lib/cuca/stdlib/listwidget/list.rb +10 -1
- data/lib/cuca_console.rb +12 -0
- data/tests/test_app/README +1 -1
- metadata +3 -4
- data/lib/cuca/urlmap-original.rb +0 -324
- data/lib/cuca/urlmap2.rb +0 -22
data/CHANGELOG
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
|
|
2
|
-
*
|
|
2
|
+
* 2009/08/20 - 0.05
|
|
3
|
+
- Widget can be defined within the action controller file.
|
|
4
|
+
- Fixed minor typos in application skeleton conf/config.rb
|
|
5
|
+
- Fix to catch exceptions in conf/config and conf/environment
|
|
6
|
+
- Fixes & minor changes in stdlib/form
|
|
7
|
+
- Stdlib listwidget rewrite_hooks will pass named hash instead of plain array
|
|
8
|
+
as row data
|
|
9
|
+
- fixed script/console to load support files
|
|
10
|
+
- Fixed bad error rescueing in generators that displayed irritating errors
|
|
11
|
+
|
|
12
|
+
* 2008/06/17 - 0.04
|
|
3
13
|
- Fixed error-message displaying traceback but not the actual exception
|
|
4
14
|
- Display trace if enabled on 'stop :error' events
|
|
5
15
|
- Option for autoloading support files (instead of bulk 'require')
|
|
@@ -12,7 +22,6 @@
|
|
|
12
22
|
- Added some unit tests
|
|
13
23
|
- Minor fixes in stdlib
|
|
14
24
|
- Some fixes in dispatchers
|
|
15
|
-
-
|
|
16
25
|
|
|
17
26
|
|
|
18
27
|
* 2008/05/18 - 0.03
|
|
@@ -17,7 +17,7 @@ class IndexController < ApplicationController
|
|
|
17
17
|
h2 { "If you want to learn cuca" }
|
|
18
18
|
ul do
|
|
19
19
|
li { text "Have a look at the Demo Widgets: "; SLink('demo', 'Here') }
|
|
20
|
-
li { text "Checkout the cuca website: "; SLink("http://cuca.rubyforge.
|
|
20
|
+
li { text "Checkout the cuca website: "; SLink("http://cuca.rubyforge.org") }
|
|
21
21
|
li { text "Read the source code of these examples" }
|
|
22
22
|
end
|
|
23
23
|
|
|
@@ -26,14 +26,14 @@ Cuca::App.configure do |config|
|
|
|
26
26
|
|
|
27
27
|
### This would be an autoload configuration
|
|
28
28
|
# config.include_directories = [
|
|
29
|
-
# { :dir => '_controllers', :class_naming
|
|
30
|
-
# { :dir => '_widgets', :class_naming
|
|
31
|
-
# { :dir => '_layouts', :class_naming
|
|
32
|
-
# { :dir => '_models', :class_naming
|
|
29
|
+
# { :dir => '_controllers', :class_naming => lambda { |f| f.capitalize+'Controller' } },
|
|
30
|
+
# { :dir => '_widgets', :class_naming => lambda { |f| f.capitalize+'Widget' } },
|
|
31
|
+
# { :dir => '_layouts', :class_naming => lambda { |f| f.capitalize+'Layout' } },
|
|
32
|
+
# { :dir => '_models', :class_naming => lambda { |f| f.capitalize } }
|
|
33
33
|
# ]
|
|
34
34
|
|
|
35
35
|
### For pretty url mapping
|
|
36
|
-
# config.magic_action_prefix = '
|
|
36
|
+
# config.magic_action_prefix = '__'
|
|
37
37
|
|
|
38
38
|
### This defines the session cookie definitions
|
|
39
39
|
# config.session_key = 'cuca_session'
|
data/lib/cuca.rb
CHANGED
|
@@ -35,6 +35,7 @@ require 'rubygems'
|
|
|
35
35
|
# All Classes are defined under this namespace
|
|
36
36
|
module Cuca
|
|
37
37
|
|
|
38
|
+
|
|
38
39
|
class CucaException < Exception # :nodoc:
|
|
39
40
|
end
|
|
40
41
|
|
|
@@ -44,6 +45,24 @@ end
|
|
|
44
45
|
|
|
45
46
|
end
|
|
46
47
|
|
|
48
|
+
# To require config and environment
|
|
49
|
+
def init_save_require(filename)
|
|
50
|
+
begin
|
|
51
|
+
require filename
|
|
52
|
+
rescue => e
|
|
53
|
+
title = "INIT Error [#{filename}]: #{e}"
|
|
54
|
+
$stderr.puts title
|
|
55
|
+
err = ''
|
|
56
|
+
e.backtrace.each do |b|
|
|
57
|
+
err << " #{b}\n"
|
|
58
|
+
end
|
|
59
|
+
$stderr.puts err
|
|
60
|
+
c = CGI.new
|
|
61
|
+
c.out { "<b>#{title}<br><br>#{err.gsub(/\n/,'<br>')}" }
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
|
|
47
66
|
|
|
48
67
|
if $cuca_path.nil? then
|
|
49
68
|
$stderr.puts "WARN: $cuca_path not found, assuming #{Dir.pwd}"
|
|
@@ -57,23 +76,12 @@ $cuca_path = File.expand_path($cuca_path) + '/'
|
|
|
57
76
|
require 'cuca/app'
|
|
58
77
|
|
|
59
78
|
$LOAD_PATH << $cuca_path+'/lib'
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
rescue LoadError => e
|
|
63
|
-
$stderr.puts "WARN: Error loading conf/config: #{e}"
|
|
64
|
-
end
|
|
79
|
+
|
|
80
|
+
init_save_require($cuca_path+'/conf/config')
|
|
65
81
|
|
|
66
82
|
require 'cuca/widget'
|
|
67
83
|
require 'cuca/controller'
|
|
68
84
|
require 'cuca/layout'
|
|
69
85
|
|
|
70
|
-
|
|
71
|
-
require $cuca_path+'/conf/environment'
|
|
72
|
-
rescue LoadError => e
|
|
73
|
-
$stderr.puts "WARN: Error loading conf/environment: #{e}"
|
|
74
|
-
rescue => e
|
|
75
|
-
e.backtrace.each do |b|
|
|
76
|
-
$stderr.puts" #{b}\n"
|
|
77
|
-
end
|
|
78
|
-
end
|
|
86
|
+
init_save_require($cuca_path+'/conf/environment')
|
|
79
87
|
|
data/lib/cuca/app.rb
CHANGED
data/lib/cuca/const.rb
CHANGED
data/lib/cuca/controller.rb
CHANGED
|
@@ -65,9 +65,8 @@ end
|
|
|
65
65
|
#
|
|
66
66
|
# == Interrupting the program
|
|
67
67
|
#
|
|
68
|
-
# If you want to stop your program you can call the 'stop' method. Stop
|
|
69
|
-
#
|
|
70
|
-
# raising an error message.
|
|
68
|
+
# If you want to stop your program you can call the 'stop' method. Stop take some arguments
|
|
69
|
+
# that allows you to redirect, display error or set a different layout.
|
|
71
70
|
#
|
|
72
71
|
#
|
|
73
72
|
# == Examples
|
|
@@ -157,7 +156,7 @@ class Controller < Widget
|
|
|
157
156
|
# One or more before filter can set by an application Controller
|
|
158
157
|
# The instance methods will be run before the action get ran (get/post/run)
|
|
159
158
|
# If you have many filters and need order you can set the priority option.
|
|
160
|
-
# Lower priorities will
|
|
159
|
+
# Lower priorities will run first.
|
|
161
160
|
public
|
|
162
161
|
def self.before_filter(method, priority = 50)
|
|
163
162
|
define_filter_method(:def_before_filter, method, priority)
|
|
@@ -7,13 +7,22 @@ class ::Markaby::Builder # :nodoc:
|
|
|
7
7
|
|
|
8
8
|
def method_missing(sym, *args, &block ) # :nodoc:
|
|
9
9
|
class_name = sym.id2name
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
|
|
11
|
+
# give up immediately if we don't have a Constant capable method
|
|
12
|
+
return old_method_missing(sym, *args, &block) if
|
|
13
|
+
class_name[0].chr.upcase != class_name[0].chr
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
widget_name = class_name+'Widget'
|
|
17
|
+
|
|
18
|
+
c=Object::const_get(widget_name) if Object::const_defined?(widget_name)
|
|
19
|
+
|
|
20
|
+
if (c.nil? && !$app.nil?) then
|
|
21
|
+
c = $app.urlmap.action_module.const_get(widget_name) if \
|
|
22
|
+
$app.urlmap.action_module.const_defined?(widget_name)
|
|
14
23
|
end
|
|
15
24
|
|
|
16
|
-
|
|
25
|
+
return old_method_missing(sym, *args, &block) if c.nil?
|
|
17
26
|
|
|
18
27
|
widget = c.new({:args => args,
|
|
19
28
|
:assigns => @assigns },
|
|
@@ -32,10 +41,11 @@ module Cuca
|
|
|
32
41
|
# A generator is a mixin to Cuca::Widget. It should provide functions that generate
|
|
33
42
|
# content.
|
|
34
43
|
# Visible within a generator function should be all instance variables, all instance
|
|
35
|
-
# methods and an easy accessor to widgets
|
|
36
|
-
#
|
|
44
|
+
# methods and an easy accessor to widgets defined on the root namespace and
|
|
45
|
+
# within the action namespace ($app.urlmap.action_namespace). For example the view and
|
|
46
|
+
# markaby generators that come with cuca you can call a widget like:
|
|
37
47
|
# Link(a,b,c..) { block}
|
|
38
|
-
# and it will initialize the LinkWidget
|
|
48
|
+
# and it will initialize the LinkWidget.
|
|
39
49
|
module Generator
|
|
40
50
|
|
|
41
51
|
# == Markaby Generator
|
data/lib/cuca/generator/view.rb
CHANGED
|
@@ -52,30 +52,36 @@ module View
|
|
|
52
52
|
@base = base_object
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
+
|
|
56
|
+
|
|
55
57
|
def method_missing(sym, *args, &block )
|
|
56
58
|
class_name = sym.id2name
|
|
59
|
+
|
|
60
|
+
# $stderr.puts "View: Method missing: #{class_name}: #{@base.class.name}"
|
|
61
|
+
|
|
62
|
+
# 1st try to find method in the base widget
|
|
63
|
+
if @base.methods.include?(class_name) then
|
|
64
|
+
return @base.send(class_name, *args, &block)
|
|
65
|
+
end
|
|
57
66
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
c=Object::const_get(class_name+"Widget")
|
|
65
|
-
rescue NameError => e
|
|
66
|
-
raise "Undefined method: #{sym.id2name}"
|
|
67
|
+
# 2nd try to find a widget in root namespace and the controllers
|
|
68
|
+
widget_name = class_name+'Widget'
|
|
69
|
+
c=Object::const_get(widget_name) if Object.const_defined?(widget_name)
|
|
70
|
+
if (c.nil? && !$app.nil?) then
|
|
71
|
+
c = $app.urlmap.action_module.const_get(widget_name) if \
|
|
72
|
+
$app.urlmap.action_module.const_defined?(widget_name)
|
|
67
73
|
end
|
|
68
74
|
|
|
75
|
+
raise "Undefined method: #{sym.id2name}" if c.nil?
|
|
76
|
+
|
|
69
77
|
widget = c.new({:args => args,
|
|
70
78
|
:assigns => @assigns },
|
|
71
79
|
&block)
|
|
72
80
|
|
|
73
|
-
# $stderr.puts "Widget:" + widget.inspect
|
|
74
|
-
return widget.to_s
|
|
75
81
|
|
|
76
|
-
|
|
82
|
+
return widget.to_s
|
|
77
83
|
end
|
|
78
|
-
|
|
84
|
+
end
|
|
79
85
|
|
|
80
86
|
|
|
81
87
|
# VIEW_DIR = $cuca_path+'app/_views'
|
data/lib/cuca/session.rb
CHANGED
|
@@ -57,6 +57,8 @@ module Cuca
|
|
|
57
57
|
#
|
|
58
58
|
# Page memory is a container to store data only valid for the current action.
|
|
59
59
|
# It will be erased once you leave to a different action.
|
|
60
|
+
# Current request and query parameters (get/post) are automatically available in this
|
|
61
|
+
# container.
|
|
60
62
|
#
|
|
61
63
|
#
|
|
62
64
|
#
|
data/lib/cuca/stdlib/arform.rb
CHANGED
|
@@ -31,11 +31,22 @@ class ARFormWidget < FormWidget
|
|
|
31
31
|
@disabled_on_create = options[:disabled_on_create] || []
|
|
32
32
|
@hidden_on_update = options[:hidden_on_update] || []
|
|
33
33
|
@hidden_on_create = options[:hidden_on_create] || []
|
|
34
|
-
super(form_name, options
|
|
34
|
+
super(form_name, options)
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
def on_submit
|
|
38
38
|
controller.send(@form_name+'_submit', @model) unless controller.nil?
|
|
39
|
+
|
|
40
|
+
# this is to reload the form with the new values in case the formname_submit did
|
|
41
|
+
# save something:
|
|
42
|
+
clear
|
|
43
|
+
form
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# overwrite this method to perform modifications
|
|
47
|
+
# before validateing the data
|
|
48
|
+
def before_validate(variables)
|
|
49
|
+
variables
|
|
39
50
|
end
|
|
40
51
|
|
|
41
52
|
def validate
|
|
@@ -44,6 +55,10 @@ class ARFormWidget < FormWidget
|
|
|
44
55
|
p = request_parameters.dup
|
|
45
56
|
p.delete(@submit_name)
|
|
46
57
|
|
|
58
|
+
|
|
59
|
+
p = before_validate(p)
|
|
60
|
+
|
|
61
|
+
|
|
47
62
|
if @model.new_record? then
|
|
48
63
|
@disabled_on_create.each { |d| p.delete(d) }
|
|
49
64
|
@hidden_on_create.each { |d| p.delete(d) }
|
|
@@ -58,7 +73,7 @@ class ARFormWidget < FormWidget
|
|
|
58
73
|
@password_fields.each do |pwf|
|
|
59
74
|
p.delete(pwf) if p[pwf].chomp.empty?
|
|
60
75
|
end
|
|
61
|
-
$stderr.puts p.inspect
|
|
76
|
+
# $stderr.puts p.inspect
|
|
62
77
|
@model.attributes = p
|
|
63
78
|
|
|
64
79
|
return true if @model.valid?
|
|
@@ -95,6 +110,12 @@ class ARFormWidget < FormWidget
|
|
|
95
110
|
"<input type='text' name='#{name}' value='#{value}' #{'disabled' unless enabled}>"
|
|
96
111
|
end
|
|
97
112
|
|
|
113
|
+
private
|
|
114
|
+
def fe_textarea(name, value, enabled, rows=4, cols = 50)
|
|
115
|
+
"<textarea name='#{name}' rows='#{rows}' cols='#{cols}'>#{value}</textarea>"
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
|
|
98
119
|
# the fe-password is special: will never contain a value and will not save the
|
|
99
120
|
# password if nothing was typed into the field
|
|
100
121
|
private
|
|
@@ -130,8 +151,9 @@ end
|
|
|
130
151
|
|
|
131
152
|
def fe_datetime(name, v,enabled)
|
|
132
153
|
v = Time.now unless v
|
|
154
|
+
v = "#{v.year}/#{twodig(v.month)}/#{twodig(v.day)} #{v.hour}:#{v.min}" if v.instance_of?(Time)
|
|
133
155
|
r = <<-EOS
|
|
134
|
-
<input type='text' name='#{name}' id='i_#{name}' value='#{v
|
|
156
|
+
<input type='text' name='#{name}' id='i_#{name}' value='#{v}' #{'disabled' unless enabled}>
|
|
135
157
|
EOS
|
|
136
158
|
if enabled then
|
|
137
159
|
r << <<-EOS
|
|
@@ -152,6 +174,35 @@ end
|
|
|
152
174
|
return r
|
|
153
175
|
end
|
|
154
176
|
|
|
177
|
+
# select date.. no time
|
|
178
|
+
def fe_date(name, v,enabled)
|
|
179
|
+
v = Time.now unless v
|
|
180
|
+
r = <<-EOS
|
|
181
|
+
<input type='text' name='#{name}' id='i_#{name}' value='#{v.year}/#{twodig(v.month)}/#{twodig(v.day)}' #{'disabled' unless enabled}>
|
|
182
|
+
EOS
|
|
183
|
+
if enabled then
|
|
184
|
+
r << <<-EOS
|
|
185
|
+
<input type='submit' id='s_#{name}' value='...'>
|
|
186
|
+
<script type="text/javascript">
|
|
187
|
+
Calendar.setup({
|
|
188
|
+
inputField : "i_#{name}", // id of the input field
|
|
189
|
+
ifFormat : "%Y/%m/%d", // format of the input field
|
|
190
|
+
showsTime : false, // will display a time selector
|
|
191
|
+
button : "s_#{name}", // trigger for the calendar (button ID)
|
|
192
|
+
singleClick : true, // double-click mode
|
|
193
|
+
step : 1 // show all years in drop-down boxes (instead of every other year as default)
|
|
194
|
+
});
|
|
195
|
+
</script>
|
|
196
|
+
</input>
|
|
197
|
+
EOS
|
|
198
|
+
end
|
|
199
|
+
return r
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def fe_time(name,v,enabled)
|
|
203
|
+
"<input name='#{name}' size=5 type='text' value='#{v || '0:00'}'#{' disabled' unless enabled}>"
|
|
204
|
+
end
|
|
205
|
+
|
|
155
206
|
def fe_bool(name,v,enabled)
|
|
156
207
|
r = ''
|
|
157
208
|
r << "<select name='#{name}' #{'disabled' unless enabled}>\n"
|
|
@@ -177,6 +228,10 @@ end
|
|
|
177
228
|
r << fe_int(name,value,enabled)
|
|
178
229
|
when :datetime
|
|
179
230
|
r << fe_datetime(name,value,enabled)
|
|
231
|
+
when :date
|
|
232
|
+
r << fe_date(name,value,enabled)
|
|
233
|
+
when :time
|
|
234
|
+
r << fe_time(name, value, enabled)
|
|
180
235
|
when :password
|
|
181
236
|
r << fe_password(name, enabled)
|
|
182
237
|
end
|
|
@@ -189,6 +244,13 @@ end
|
|
|
189
244
|
fe(col.type, col.name, @model.send(column_name.intern))
|
|
190
245
|
end
|
|
191
246
|
|
|
247
|
+
|
|
248
|
+
# Load column values into instance variables
|
|
249
|
+
def setup
|
|
250
|
+
@model.class.columns.each do |col|
|
|
251
|
+
self.instance_variable_set("@#{col.name}", @model.send(col.name.intern))
|
|
252
|
+
end
|
|
253
|
+
end
|
|
192
254
|
|
|
193
255
|
# you might want to replace this method
|
|
194
256
|
public
|
data/lib/cuca/stdlib/form.rb
CHANGED
|
@@ -53,25 +53,38 @@ class FormWidget < Cuca::Widget
|
|
|
53
53
|
# {form_name}_submit(result) on the CONTROLLER.
|
|
54
54
|
def on_submit
|
|
55
55
|
controller.send(@form_name+'_submit', get_variables) unless controller.nil?
|
|
56
|
+
clear
|
|
57
|
+
form
|
|
56
58
|
end
|
|
57
59
|
|
|
58
|
-
|
|
60
|
+
# options can be used for form specific stuff
|
|
61
|
+
# we only use :post_to to set @post_to atm
|
|
62
|
+
def output(form_name, options = {})
|
|
59
63
|
@form_name = form_name
|
|
60
|
-
|
|
64
|
+
|
|
61
65
|
@submit_name = 'submit_'+@form_name
|
|
62
66
|
@form_errors = {}
|
|
63
67
|
|
|
68
|
+
@options = options
|
|
69
|
+
|
|
70
|
+
setup
|
|
71
|
+
|
|
72
|
+
@post_to = @options[:post_to] || cgi.path_info
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
# form
|
|
76
|
+
|
|
64
77
|
if posted? then
|
|
65
78
|
load_variables
|
|
66
79
|
validate
|
|
67
80
|
if @form_errors.empty? then
|
|
68
|
-
|
|
81
|
+
# What was that thought about?
|
|
82
|
+
# clear # submitted forms should not have any content that might have been generated
|
|
69
83
|
return on_submit
|
|
70
84
|
else
|
|
71
85
|
form
|
|
72
86
|
end
|
|
73
87
|
else
|
|
74
|
-
setup
|
|
75
88
|
form
|
|
76
89
|
end
|
|
77
90
|
end
|
|
@@ -20,10 +20,19 @@ class BaseList < Cuca::Widget
|
|
|
20
20
|
@rewrite_hooks[field_id] = proc
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
+
def row2hash(row)
|
|
24
|
+
res = {}
|
|
25
|
+
c = columns
|
|
26
|
+
c.each_index do |idx|
|
|
27
|
+
res[c[idx][:id]] = row[idx]
|
|
28
|
+
end
|
|
29
|
+
res
|
|
30
|
+
end
|
|
31
|
+
|
|
23
32
|
def rewrite_field(row, field_id, content)
|
|
24
33
|
# $stderr.puts "REwrite field(#{row.inspect}, #{field_id.inspect}, #{content.inspect} - hooks #{@rewrite_hooks.inspect}"
|
|
25
34
|
return content unless @rewrite_hooks[field_id]
|
|
26
|
-
return @rewrite_hooks[field_id].call(row, content)
|
|
35
|
+
return @rewrite_hooks[field_id].call(row2hash(row), content)
|
|
27
36
|
end
|
|
28
37
|
|
|
29
38
|
|
data/lib/cuca_console.rb
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# This file is -r required when runnung script/console to load
|
|
2
|
+
# support files automatically.
|
|
3
|
+
# Only for the CLI irb console
|
|
4
|
+
|
|
5
|
+
require 'cuca/urlmap'
|
|
6
|
+
|
|
7
|
+
puts "Cuca console: type: url [/some/path] to load support files of your app"
|
|
8
|
+
$app = Cuca::App.new
|
|
9
|
+
|
|
10
|
+
def url(some_path)
|
|
11
|
+
$app.load_support_files(Cuca::URLMap.new($cuca_path+'/app', some_path))
|
|
12
|
+
end
|
data/tests/test_app/README
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
This directory is for the unit tests, it doesn't make sense for anything else.
|
|
1
|
+
This directory is for the unit tests, it doesn't make sense for anything else.
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: cuca
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: "0.
|
|
4
|
+
version: "0.05"
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Martin Boese
|
|
@@ -9,7 +9,7 @@ autorequire:
|
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
11
|
|
|
12
|
-
date: 2008-
|
|
12
|
+
date: 2008-08-20 00:00:00 +00:00
|
|
13
13
|
default_executable:
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
@@ -41,12 +41,11 @@ extra_rdoc_files:
|
|
|
41
41
|
files:
|
|
42
42
|
- bin/cuca
|
|
43
43
|
- lib/cuca.rb
|
|
44
|
+
- lib/cuca_console.rb
|
|
44
45
|
- lib/cuca
|
|
45
46
|
- lib/cuca/cgi_fix.rb
|
|
46
47
|
- lib/cuca/controller.rb
|
|
47
48
|
- lib/cuca/config.rb
|
|
48
|
-
- lib/cuca/urlmap2.rb
|
|
49
|
-
- lib/cuca/urlmap-original.rb
|
|
50
49
|
- lib/cuca/stdlib
|
|
51
50
|
- lib/cuca/stdlib/arview.rb
|
|
52
51
|
- lib/cuca/stdlib/form.rb
|
data/lib/cuca/urlmap-original.rb
DELETED
|
@@ -1,324 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
if __FILE__ == $0 then
|
|
3
|
-
require 'rubygems'
|
|
4
|
-
require 'cuca'
|
|
5
|
-
end
|
|
6
|
-
|
|
7
|
-
module Cuca
|
|
8
|
-
|
|
9
|
-
# URLMap will throw this in case we can't find a controller
|
|
10
|
-
# file for a URL.
|
|
11
|
-
class RoutingError < StandardError # :nodoc:
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
# == URLMap
|
|
16
|
-
#
|
|
17
|
-
# URLMap is used internally to match a URL to a controller file.
|
|
18
|
-
# Call with ds = URLMap.new('/path/to/app', 'path/from/url')
|
|
19
|
-
# URLMap.new(base_path, url)
|
|
20
|
-
#
|
|
21
|
-
# You can then fetch the following values:
|
|
22
|
-
#
|
|
23
|
-
# * script - path to the controller file
|
|
24
|
-
# * url - unmodified URL as passed to initializer
|
|
25
|
-
# * assigns - hash with variable assigns from the url (magick prefixes)
|
|
26
|
-
# * subcall - name of subcall or nil if a normal call was made
|
|
27
|
-
# * action - Action name (Note: action.capitalize+"Controller" is your controller class name)
|
|
28
|
-
# * base_url - Base URL to the action (e.g.: /user/someone/show is -> /user/someone/)
|
|
29
|
-
# * base_path - Unmodified base_path
|
|
30
|
-
# * action_path - Path to the action script
|
|
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)
|
|
34
|
-
# * action_module - The module the action should be loaded into (to avoid name conflicts, depends on action_path)
|
|
35
|
-
#
|
|
36
|
-
#
|
|
37
|
-
# == Match on other URL
|
|
38
|
-
#
|
|
39
|
-
# A widget/controller can make use of the URLMap object to scan on other directories (example to find out if a
|
|
40
|
-
# link url will be withing the same controller).
|
|
41
|
-
#
|
|
42
|
-
# See match? / submatch? and usubmatch?
|
|
43
|
-
#
|
|
44
|
-
#
|
|
45
|
-
# == Notes
|
|
46
|
-
#
|
|
47
|
-
# URL's ending with '/' will be scanned for default index files.
|
|
48
|
-
#
|
|
49
|
-
# URL's where last part (action) starts with '-' will be scanned for
|
|
50
|
-
# subcalls
|
|
51
|
-
#
|
|
52
|
-
# If no script is found or any other error it will raise a RoutingError exception
|
|
53
|
-
#
|
|
54
|
-
#
|
|
55
|
-
# == Example
|
|
56
|
-
#
|
|
57
|
-
# u = URLMap.new('/home/bones/src/cuca_app/app', 'customer/southwind_lda/show'
|
|
58
|
-
#
|
|
59
|
-
# u.script => '/home/bones/src/cuca_app/app/customer/__customer/show.rb'
|
|
60
|
-
# u.action => 'show'
|
|
61
|
-
# u.base_url => '/customer/__customer/'
|
|
62
|
-
# u.assigns => { 'customer' => 'southwind_lda' }
|
|
63
|
-
# u.action_path => 'customer/southwind_lda/'
|
|
64
|
-
#
|
|
65
|
-
class URLMap
|
|
66
|
-
attr_reader :url # current url
|
|
67
|
-
attr_reader :assigns
|
|
68
|
-
attr_reader :script
|
|
69
|
-
attr_reader :subcall
|
|
70
|
-
attr_reader :base_url
|
|
71
|
-
attr_reader :base_path
|
|
72
|
-
attr_reader :action
|
|
73
|
-
attr_reader :action_path
|
|
74
|
-
attr_reader :action_path_full
|
|
75
|
-
attr_reader :action_module
|
|
76
|
-
attr_reader :path_tree
|
|
77
|
-
|
|
78
|
-
DEF_ACT = Cuca::App::config['magic_action_prefix'] || '__'
|
|
79
|
-
DEF_IDX = [ 'index', 'default' ]
|
|
80
|
-
|
|
81
|
-
private
|
|
82
|
-
def scan_file(base, file)
|
|
83
|
-
|
|
84
|
-
if (file == '') then # check for default index file
|
|
85
|
-
DEF_IDX.each do |idxfile|
|
|
86
|
-
if File.exist?("#{base}/#{idxfile}.rb")
|
|
87
|
-
@action = idxfile
|
|
88
|
-
return "#{idxfile}.rb"
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
raise RoutingError.new("No default index file found in #{base}")
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
@action = file
|
|
95
|
-
|
|
96
|
-
# check if a regular file exists:
|
|
97
|
-
# puts "Checking file on #{check}"
|
|
98
|
-
return (file+".rb") if File.exist?("#{base}/#{file}.rb")
|
|
99
|
-
|
|
100
|
-
# check if the subcall file exists:
|
|
101
|
-
if (file[0].chr == '-') then
|
|
102
|
-
(action,subcall) = file.scan(/^\-(.*)\-(.*)$/).flatten
|
|
103
|
-
if action.nil? || subcall.nil? || action.strip.empty? then
|
|
104
|
-
raise RoutingError.new("Bad format on subcall: #{file}")
|
|
105
|
-
end
|
|
106
|
-
raise RoutingError.new("Script not found for subcall: #{file}: #{action}.rb") if !File.exist?("#{base}/#{action}.rb")
|
|
107
|
-
@subcall = subcall
|
|
108
|
-
@action = action
|
|
109
|
-
return "#{action}.rb"
|
|
110
|
-
end
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
# scan_dir will look within a realdirectory for an unparsed url 'file' and return
|
|
115
|
-
# it's real path
|
|
116
|
-
private
|
|
117
|
-
def scan_dir(base, file)
|
|
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
|
-
|
|
124
|
-
|
|
125
|
-
if mount["#{striped}/"] then
|
|
126
|
-
$stderr.puts "Found mount point, returning: #{mount["#{striped}/"]}"
|
|
127
|
-
return mount["#{striped}/"]
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
if File.directory?("#{base}/#{file}") then
|
|
131
|
-
return file.empty? ? base : "#{base}/#{file}" # avoid returning double //
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
d = Dir["#{base}/#{DEF_ACT}*"].collect { |f| f.split('/').last }
|
|
135
|
-
|
|
136
|
-
# puts "Directory not found, checking for default in #{base} - #{file}"
|
|
137
|
-
|
|
138
|
-
# puts d.inspect
|
|
139
|
-
#
|
|
140
|
-
|
|
141
|
-
raise RoutingError.new("Multiple default actions defined in #{base}") if d.size > 1
|
|
142
|
-
raise RoutingError.new("Routing Error in #{base}") if d.empty?
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
@assigns[d[0][DEF_ACT.size..-1]] = file
|
|
146
|
-
"#{base}/#{d[0]}"
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
private
|
|
151
|
-
def make_module(path)
|
|
152
|
-
const_name = "Appmod_#{path.gsub(/[\/\\]/, '_')}"
|
|
153
|
-
|
|
154
|
-
if Cuca::Objects::const_defined?(const_name.intern) then
|
|
155
|
-
return Cuca::Objects::const_get(const_name.intern)
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
m = Module.new
|
|
159
|
-
Cuca::Objects::const_set(const_name.intern, m)
|
|
160
|
-
return m
|
|
161
|
-
end
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
# scan will match an URI to a script and set assigns. (called from initialize)
|
|
165
|
-
private
|
|
166
|
-
def scan
|
|
167
|
-
files = @path_info.split('/')
|
|
168
|
-
|
|
169
|
-
files << '' if @path_info[@path_info.size-1].chr == '/' # add empty element if we point to a directory
|
|
170
|
-
|
|
171
|
-
# files now contains something like:
|
|
172
|
-
# [users, show, martin, contacts]
|
|
173
|
-
|
|
174
|
-
# puts files.inspect
|
|
175
|
-
real_path = @base_path.dup
|
|
176
|
-
|
|
177
|
-
# scan directory
|
|
178
|
-
files.each_index do |idx|
|
|
179
|
-
next if idx >= (files.size-1) # skip last element
|
|
180
|
-
r = scan_dir(real_path, files[idx])
|
|
181
|
-
raise RoutingError.new("Routing Error at #{real_path} - #{files[idx]}") if !r
|
|
182
|
-
@path_tree << r
|
|
183
|
-
real_path = r
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
@url = @path_info
|
|
187
|
-
@base_url = "#{files[0..-2].join('/')}/"
|
|
188
|
-
@action_path = real_path[@base_path.length..-1]
|
|
189
|
-
@action_path_full = real_path
|
|
190
|
-
@action_module = make_module(@action_path)
|
|
191
|
-
|
|
192
|
-
# scan file (last element)
|
|
193
|
-
r = scan_file(real_path, files.last)
|
|
194
|
-
|
|
195
|
-
raise RoutingError.new("Routing Error - script not found at #{real_path} - #{files.last}") if !r
|
|
196
|
-
|
|
197
|
-
real_path = "#{real_path}/#{r}"
|
|
198
|
-
|
|
199
|
-
@script = File.expand_path(real_path)
|
|
200
|
-
# @path_tree = _tree(@base_path, @script)
|
|
201
|
-
self
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
# match will check if the supplied url maches with a script
|
|
206
|
-
# returns boolean
|
|
207
|
-
#
|
|
208
|
-
# Example:
|
|
209
|
-
# URLMap('/path/to/app', '/customer/southwind_lda/').match?('/path/to/app/customer/__custid/index.rb') => true
|
|
210
|
-
public
|
|
211
|
-
def match?(script)
|
|
212
|
-
m_script = @script
|
|
213
|
-
p_script = File.expand_path(script)
|
|
214
|
-
|
|
215
|
-
# $stderr.puts "URLMap::match - #{m_script} - #{p_script}"
|
|
216
|
-
return (m_script == p_script)
|
|
217
|
-
rescue RoutingError
|
|
218
|
-
false
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
# this will match if the current script can be found within a path
|
|
223
|
-
# from the parameters.
|
|
224
|
-
#
|
|
225
|
-
# Example:
|
|
226
|
-
# URLMap('/path/to/app', '/customer/southwind_lda/').submatch?('/customer/__custid/') => true
|
|
227
|
-
public
|
|
228
|
-
def submatch?(some_path)
|
|
229
|
-
# $stderr.puts "Submatch: #{some_path} with #{@script} - #{(@script.length < some_path.length).inspect} #{@script.include?(some_path)}"
|
|
230
|
-
return false if @script.length < some_path.length
|
|
231
|
-
return @script.include?(some_path)
|
|
232
|
-
end
|
|
233
|
-
|
|
234
|
-
# this will match the current script to a part of a url (link):
|
|
235
|
-
#
|
|
236
|
-
# Example:
|
|
237
|
-
# URLMap('/path/to/app', '/customer/southwind_lda/').submatch?('/customer/other_customer/') => true
|
|
238
|
-
public
|
|
239
|
-
def usubmatch?(some_path)
|
|
240
|
-
@path_info.include?(some_path)
|
|
241
|
-
end
|
|
242
|
-
|
|
243
|
-
# FIXME: needed?
|
|
244
|
-
public
|
|
245
|
-
def has_script?(script)
|
|
246
|
-
return !(@script == '')
|
|
247
|
-
end
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
def initialize(base_path, path_info, default_actions = ['index'])
|
|
251
|
-
@path_info = path_info
|
|
252
|
-
@base_path = File.expand_path(base_path)
|
|
253
|
-
@script = ''
|
|
254
|
-
@subcall = nil
|
|
255
|
-
@default_actions = default_actions
|
|
256
|
-
@assigns = {}
|
|
257
|
-
@action = ''
|
|
258
|
-
@action_path = ''
|
|
259
|
-
@path_tree = [base_path]
|
|
260
|
-
scan
|
|
261
|
-
self
|
|
262
|
-
end
|
|
263
|
-
|
|
264
|
-
end
|
|
265
|
-
|
|
266
|
-
end
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
#
|
|
270
|
-
# Testings:
|
|
271
|
-
#
|
|
272
|
-
|
|
273
|
-
if __FILE__ == $0 then
|
|
274
|
-
require 'app'
|
|
275
|
-
|
|
276
|
-
BASE = '/home/bones/src/cuca/app'
|
|
277
|
-
URL = 'user/martin/somewhere/notexist/'
|
|
278
|
-
|
|
279
|
-
puts "Testing on '#{BASE}' - '#{URL}'"
|
|
280
|
-
|
|
281
|
-
module Cuca
|
|
282
|
-
ds = URLMap.new(BASE, URL)
|
|
283
|
-
begin
|
|
284
|
-
rescue RoutingError => e
|
|
285
|
-
puts "E: Invalid request #{$!}"
|
|
286
|
-
end
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
puts "Match with: #{ds.match?('/home/bones/src/cuca/app/user/__default_username/index.rb')}"
|
|
291
|
-
puts "Submatch with /user/__username/ #{ds.submatch?('/user/__username/')}"
|
|
292
|
-
puts "Submatch with '/user/' #{ds.submatch?('/user/')}"
|
|
293
|
-
puts "USubmatch with '/user/' #{ds.usubmatch?('/user/martin')}"
|
|
294
|
-
puts
|
|
295
|
-
puts "Script is: #{ds.script}"
|
|
296
|
-
puts "Assigns are: #{ds.assigns.inspect}"
|
|
297
|
-
puts "Subcall: #{ds.subcall.inspect}"
|
|
298
|
-
puts "Action: #{ds.action}"
|
|
299
|
-
puts "Action Path: #{ds.action_path}"
|
|
300
|
-
puts "Action Path Full: #{ds.action_path_full}"
|
|
301
|
-
puts "Action Module: #{ds.action_module.inspect}"
|
|
302
|
-
puts "Path tree: #{ds.path_tree.inspect}"
|
|
303
|
-
end
|
|
304
|
-
|
|
305
|
-
end
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
# URL: "/user/martin/show"
|
|
314
|
-
# DIR: "/user/__userid/show'
|
|
315
|
-
# MOUNT: "/user/__userid/" =>>> "/plugin/user" contains 'show'
|
|
316
|
-
# MOUNT: "/user/__userid/" =>>> "/plugin/user2" contains 'see'
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
data/lib/cuca/urlmap2.rb
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
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
|