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 CHANGED
@@ -1,5 +1,15 @@
1
1
 
2
- * xxxx/xx/xx - 0.04
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.net") }
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 = Proc.new { |f| f.capitalize+'Controller' } },
30
- # { :dir => '_widgets', :class_naming = Proc.new { |f| f.capitalize+'Widget' } },
31
- # { :dir => '_layouts', :class_naming = Proc.new { |f| f.capitalize+'Layout' } }
32
- # { :dir => '_models', :class_naming = Proc.new { |f| f.capitalize } }
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 = '__default_'
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
- begin
61
- require $cuca_path+'/conf/config'
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
- begin
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
@@ -232,7 +232,7 @@ class App
232
232
  # 3rd: Load additional files
233
233
  load_support_files(@urlmap)
234
234
 
235
- test = ApplicationController.new
235
+ # test = ApplicationController.new
236
236
 
237
237
 
238
238
  # 4th: Now let's run the actual page script code
data/lib/cuca/const.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Cuca
2
- VERSION = '0.04'
2
+ VERSION = '0.05'
3
3
  end
@@ -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 has
69
- # function to do most function, like redirect or setting a different layout or
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 be ran first.
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
- begin
11
- c=Object::const_get(class_name+"Widget")
12
- rescue NameError => e
13
- return old_method_missing(sym,*args,&block)
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
- # $stderr.puts "Widget in markaby: Class: #{class_name}, \n\n assigns: #{@assigns.inspect} \n\n"
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. For example the view and markaby generators
36
- # that come with cuca you can call a widget like:
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
@@ -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
- begin
59
- # 1st try to find method in the base widget
60
- if @base.methods.include?(class_name) then
61
- return @base.send(class_name, *args, &block)
62
- end
63
- # 2nd try to find a widget
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
- # $stderr.puts "Good"
82
+ return widget.to_s
77
83
  end
78
- end
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
  #
@@ -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[:post_to])
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.year}/#{twodig(v.month)}/#{twodig(v.day)} #{v.hour}:#{v.min}' #{'disabled' unless enabled}>
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
@@ -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
- def output(form_name, post_to = nil)
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
- @post_to = post_to || cgi.path_info
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
- clear # submitted forms should not have any content that might have been generated
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
 
@@ -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
@@ -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.04"
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-06-17 00:00:00 +01:00
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
@@ -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