ramaze 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. data/Rakefile +14 -29
  2. data/bin/ramaze +2 -3
  3. data/doc/AUTHORS +5 -2
  4. data/doc/CHANGELOG +262 -9
  5. data/doc/FAQ +6 -6
  6. data/doc/meta/announcement.txt +5 -19
  7. data/doc/tutorial/todolist.html +47 -57
  8. data/doc/tutorial/todolist.mkd +47 -55
  9. data/examples/memleak_detector.rb +31 -0
  10. data/examples/todolist/src/controller/main.rb +14 -13
  11. data/examples/todolist/src/element/page.rb +2 -2
  12. data/examples/todolist/src/model.rb +2 -2
  13. data/examples/todolist/todolist.db +0 -4
  14. data/examples/whywiki/main.rb +2 -2
  15. data/examples/whywiki/template/edit.xhtml +1 -1
  16. data/examples/whywiki/template/show.xhtml +3 -3
  17. data/lib/proto/src/controller/main.rb +18 -1
  18. data/lib/proto/template/index.xhtml +11 -2
  19. data/lib/ramaze.rb +1 -1
  20. data/lib/ramaze/action.rb +104 -5
  21. data/lib/ramaze/action/render.rb +54 -0
  22. data/lib/ramaze/adapter.rb +2 -1
  23. data/lib/ramaze/adapter/mongrel.rb +13 -4
  24. data/lib/ramaze/cache.rb +17 -8
  25. data/lib/ramaze/cache/memcached.rb +1 -5
  26. data/lib/ramaze/controller.rb +51 -18
  27. data/lib/ramaze/controller/resolve.rb +19 -14
  28. data/lib/ramaze/dispatcher.rb +13 -16
  29. data/lib/ramaze/dispatcher/action.rb +2 -3
  30. data/lib/ramaze/dispatcher/error.rb +8 -3
  31. data/lib/ramaze/dispatcher/file.rb +1 -4
  32. data/lib/ramaze/error.rb +5 -5
  33. data/lib/ramaze/global.rb +7 -1
  34. data/lib/ramaze/global/globalstruct.rb +1 -3
  35. data/lib/ramaze/helper/aspect.rb +8 -10
  36. data/lib/ramaze/helper/cgi.rb +21 -3
  37. data/lib/ramaze/helper/identity.rb +4 -6
  38. data/lib/ramaze/helper/link.rb +4 -4
  39. data/lib/ramaze/helper/pager.rb +316 -0
  40. data/lib/ramaze/helper/partial.rb +37 -0
  41. data/lib/ramaze/helper/stack.rb +1 -1
  42. data/lib/ramaze/inform.rb +9 -0
  43. data/lib/ramaze/inform/hub.rb +5 -0
  44. data/lib/ramaze/inform/informer.rb +12 -6
  45. data/lib/ramaze/inform/informing.rb +32 -7
  46. data/lib/ramaze/inform/knotify.rb +21 -0
  47. data/lib/ramaze/inform/xosd.rb +58 -24
  48. data/lib/ramaze/sourcereload.rb +30 -1
  49. data/lib/ramaze/template.rb +33 -12
  50. data/lib/ramaze/template/amrita2.rb +21 -20
  51. data/lib/ramaze/template/erubis.rb +18 -14
  52. data/lib/ramaze/template/ezamar.rb +15 -26
  53. data/lib/ramaze/template/ezamar/element.rb +1 -1
  54. data/lib/ramaze/template/ezamar/engine.rb +45 -36
  55. data/lib/ramaze/template/ezamar/morpher.rb +3 -3
  56. data/lib/ramaze/template/ezamar/render_partial.rb +26 -0
  57. data/lib/ramaze/template/haml.rb +23 -18
  58. data/lib/ramaze/template/liquid.rb +5 -3
  59. data/lib/ramaze/template/markaby.rb +14 -11
  60. data/lib/ramaze/template/remarkably.rb +11 -5
  61. data/lib/ramaze/tool/localize.rb +12 -4
  62. data/lib/ramaze/tool/tidy.rb +26 -23
  63. data/lib/ramaze/trinity/request.rb +11 -7
  64. data/lib/ramaze/trinity/session.rb +24 -8
  65. data/lib/ramaze/version.rb +1 -1
  66. data/rake_tasks/maintaince.rake +136 -11
  67. data/spec/examples/templates/template_liquid.rb +6 -3
  68. data/spec/examples/todolist.rb +1 -2
  69. data/spec/helper/minimal.rb +7 -7
  70. data/spec/ramaze/action/basics.rb +19 -0
  71. data/spec/ramaze/action/render.rb +18 -0
  72. data/spec/ramaze/controller.rb +1 -1
  73. data/spec/ramaze/controller/template_resolving.rb +1 -1
  74. data/spec/ramaze/dispatcher/file.rb +24 -0
  75. data/spec/ramaze/error.rb +28 -29
  76. data/spec/ramaze/helper/cgi.rb +43 -0
  77. data/spec/ramaze/helper/pager.rb +27 -0
  78. data/spec/ramaze/helper/partial.rb +38 -0
  79. data/spec/ramaze/helper/template/partial.xhtml +1 -0
  80. data/spec/ramaze/inform/informer.rb +1 -1
  81. data/spec/ramaze/localize.rb +1 -1
  82. data/spec/ramaze/morpher.rb +3 -3
  83. data/spec/ramaze/request.rb +1 -3
  84. data/spec/ramaze/template.rb +9 -7
  85. data/spec/ramaze/template/haml.rb +2 -1
  86. metadata +21 -7
  87. data/examples/todolist/public/404.jpg +0 -0
  88. data/examples/todolist/public/error.xhtml +0 -74
  89. data/lib/ramaze/controller/render.rb +0 -90
@@ -11,7 +11,7 @@ module Ramaze
11
11
  # For your own usage you should use another namespace.
12
12
 
13
13
  def initialize(host = 'localhost', port = '11211', namespace = 'ramaze')
14
- @cache = MemCache.new("#{host}:#{port}", :namespace => namespace)
14
+ @cache = MemCache.new("#{host}:#{port}", :namespace => namespace, :multithread => true)
15
15
  end
16
16
 
17
17
  # please read the documentation of memcache-client for further methods.
@@ -73,11 +73,7 @@ class MemCache
73
73
 
74
74
  class Server
75
75
  def flush_all
76
- @mutex.lock if @multithread
77
-
78
76
  socket.write "flush_all\r\n"
79
- ensure
80
- @mutex.unlock if @multithread
81
77
  end
82
78
  end
83
79
  end
@@ -6,7 +6,6 @@ require 'ramaze/template'
6
6
  require 'ramaze/action'
7
7
 
8
8
  require 'ramaze/controller/resolve'
9
- require 'ramaze/controller/render'
10
9
  require 'ramaze/controller/error'
11
10
 
12
11
  module Ramaze
@@ -19,8 +18,6 @@ module Ramaze
19
18
 
20
19
  helper :redirect, :link, :file, :flash, :cgi
21
20
 
22
- trait[:template_extensions] ||= {}
23
-
24
21
  # Whether or not to map this controller on startup automatically
25
22
 
26
23
  trait[:automap] ||= true
@@ -29,24 +26,33 @@ module Ramaze
29
26
 
30
27
  trait[:map] ||= nil
31
28
 
29
+ # Modules that are excluded from the Action lookup
30
+
32
31
  trait :exclude_action_modules => [Kernel, Object, PP::ObjectMixin]
33
32
 
33
+ # Caches patterns for the given path.
34
+
34
35
  trait :pattern_cache => Hash.new{|h,k| h[k] = Controller.pattern_for(k) }
35
36
 
36
37
  class << self
37
38
  include Ramaze::Helper
38
39
  extend Ramaze::Helper
39
40
 
41
+ # When Controller is subclassed the resulting class is placed in
42
+ # Global.controllers and a new trait :actions_cached is set on it.
43
+
40
44
  def inherited controller
41
45
  controller.trait :actions_cached => Set.new
42
46
  Global.controllers << controller
43
47
  end
44
48
 
49
+ # called from Ramaze.startup, adds Cache.actions and Cache.patterns, walks
50
+ # all controllers subclassed so far and adds them to the Global.mapping if
51
+ # they are not assigned yet.
52
+
45
53
  def startup options = {}
46
54
  Inform.debug("found Controllers: #{Global.controllers.inspect}")
47
55
 
48
- Cache.add :actions, :patterns
49
-
50
56
  Global.controllers.each do |controller|
51
57
  if map = controller.mapping
52
58
  Inform.debug("mapping #{map} => #{controller}")
@@ -57,25 +63,37 @@ module Ramaze
57
63
  Inform.debug("mapped Controllers: #{Global.mapping.inspect}")
58
64
  end
59
65
 
66
+ # checks paths for existance and logs a warning if it doesn't exist yet.
67
+
60
68
  def check_path(path, message)
61
69
  Inform.warn(message) unless File.directory?(path)
62
70
  end
63
71
 
72
+ # if trait[:automap] is set and controller is not in Global.mapping yet
73
+ # this will build a new default mapping-point, (Main|Base|Index)* are put
74
+ # at '/' by default.
75
+
64
76
  def mapping
65
77
  global_mapping = Global.mapping.invert[self]
66
78
  return global_mapping if global_mapping
67
79
  if ancestral_trait[:automap]
68
80
  name = self.to_s.gsub('Controller', '').split('::').last
69
- %w[Main Base Index].include?(name) ? '/' : "/#{name.snake_case}"
81
+ name == 'Main' ? '/' : "/#{name.snake_case}"
70
82
  end
71
83
  end
72
84
 
85
+ # Map Controller to the given syms or strings.
86
+
73
87
  def map(*syms)
74
88
  syms.each do |sym|
75
89
  Global.mapping[sym.to_s] = self
76
90
  end
77
91
  end
78
92
 
93
+ # Define a template_root for Controller, returns the current template_root
94
+ # if no argument is given.
95
+ # Runs every given path through Controller::check_path
96
+
79
97
  def template_root path = nil
80
98
  if path
81
99
  message = "#{self}.template_root is #{path} which does not exist"
@@ -86,33 +104,48 @@ module Ramaze
86
104
  end
87
105
  end
88
106
 
89
- def public_root path = nil
90
- if path
91
- message = "#{self}.public_root is #{path} which does not exist"
92
- check_path(path, message)
93
- @public_root = path
94
- else
95
- @public_root
96
- end
97
- end
107
+ # This is used for template rerouting, takes action, optionally a
108
+ # controller and action to route to.
109
+ #
110
+ # Usage:
111
+ # class MainController
112
+ # template :index, OtherController, :list
113
+ # template :foo, :bar
114
+ #
115
+ # def index
116
+ # 'will use template from OtherController#list'
117
+ # end
118
+ #
119
+ # def foo
120
+ # 'will use template from self#bar'
121
+ # end
122
+ # end
98
123
 
99
124
  def template(this, from, that = nil)
100
125
  from, that = self, from unless that
101
126
  trait "#{this}_template" => [from, that.to_s]
102
127
  end
103
128
 
129
+ # Return Controller of current Action
130
+
104
131
  def current
105
- Thread.current[:controller]
132
+ action = Action.current
133
+ action.instance || action.controller
106
134
  end
107
135
 
136
+ # Entering point for Dispatcher, first Controller::resolve(path) and then
137
+ # renders the resulting Action.
138
+
108
139
  def handle path
109
- controller, action = *resolve(path)
110
- controller.render(action)
140
+ action = resolve(path)
141
+ action.render
111
142
  end
112
143
  end
113
144
 
114
145
  private
115
146
 
147
+ # Simplistic render, rerouting to Controller.handle(*args)
148
+
116
149
  def render *args
117
150
  self.class.handle(*args)
118
151
  end
@@ -13,7 +13,10 @@ module Ramaze
13
13
  # manveru: everything further down is considered 500
14
14
 
15
15
  def resolve(path)
16
- #Inform.debug("resolve_controller('#{path}')")
16
+ if found = Cache.resolved[path]
17
+ return found
18
+ end
19
+
17
20
  mapping = Global.mapping
18
21
  controllers = Global.controllers
19
22
 
@@ -31,7 +34,7 @@ module Ramaze
31
34
 
32
35
  valid_action = (action.method or (params.empty? && action.template))
33
36
 
34
- return controller, action if valid_action
37
+ return Cache.resolved[path] = action if valid_action
35
38
  end
36
39
  end
37
40
 
@@ -52,8 +55,11 @@ module Ramaze
52
55
  template ||= resolve_template(path)
53
56
  end
54
57
 
55
- hash = {:method => method, :params => params, :template => template}
56
- Action.fill(hash)
58
+ Action.create :path => path,
59
+ :method => method,
60
+ :params => params,
61
+ :template => template,
62
+ :controller => self
57
63
  end
58
64
 
59
65
  def resolve_template(action)
@@ -68,13 +74,8 @@ module Ramaze
68
74
  end
69
75
 
70
76
  def template_paths
71
- first_path =
72
- if template_root = @template_root
73
- template_root
74
- else
75
- Global.template_root / Global.mapping.invert[self]
76
- end
77
- [ first_path, public_root, Global.public_root ].compact
77
+ @template_root ||= Global.template_root / Global.mapping.invert[self]
78
+ [ @template_root, Global.public_root, Global.public_proto ].compact
78
79
  end
79
80
 
80
81
  def resolve_method(name, *params)
@@ -128,17 +129,21 @@ module Ramaze
128
129
  end
129
130
 
130
131
  def extension_order
131
- t_extensions = Controller.trait[:template_extensions]
132
+ t_extensions = Template::ENGINES
132
133
  engine = trait[:engine]
133
- c_extensions = t_extensions.reject{|k,v| v != engine}.keys
134
- all_extensions = t_extensions.keys
134
+ c_extensions = t_extensions.select{|k,v| k == engine}.map{|k,v| v}.flatten
135
+ all_extensions = t_extensions.map{|k,v| v}.flatten
135
136
  (c_extensions + all_extensions).uniq
136
137
  end
137
138
 
139
+ # Raises Ramaze::Error::NoController
140
+
138
141
  def raise_no_controller(path)
139
142
  raise Ramaze::Error::NoController, "No Controller found for `#{path}'"
140
143
  end
141
144
 
145
+ # Raises Ramaze::Error::NoAction
146
+
142
147
  def raise_no_action(controller, path)
143
148
  raise Ramaze::Error::NoAction, "No Action found for `#{path}' on #{controller}"
144
149
  end
@@ -14,21 +14,9 @@ require 'ramaze/dispatcher/file'
14
14
  module Ramaze
15
15
  module Dispatcher
16
16
 
17
- trait :dispatch => [
18
- Dispatcher::File,
19
- Dispatcher::Action,
20
- ]
21
-
22
- trait :handle_error => {
23
- Exception =>
24
- [ STATUS_CODE["Internal Server Error"], '/error' ],
25
- Ramaze::Error::NoAction =>
26
- [ STATUS_CODE["Not Found"], '/error' ],
27
- Ramaze::Error::NoController =>
28
- [ STATUS_CODE["Not Found"], '/error' ],
29
- }
30
-
31
- Cache.add :shield
17
+ # requests are passed to every
18
+
19
+ FILTER = [ Dispatcher::File, Dispatcher::Action ] unless defined?(FILTER)
32
20
 
33
21
  trait :shielded => [ STATUS_CODE["Not Found"] ]
34
22
 
@@ -88,14 +76,20 @@ module Ramaze
88
76
  end
89
77
  end
90
78
 
79
+ # Calls .process(path) on every class in Dispatcher::FILTER until one
80
+ # returns something else than false/nil.
81
+ # Raises NoAction otherwise.
82
+
91
83
  def filter path
92
- trait[:dispatch].each do |dispatcher|
84
+ FILTER.each do |dispatcher|
93
85
  result = dispatcher.process(path)
94
86
  return result if result
95
87
  end
96
88
  raise Ramaze::Error::NoAction, "No Dispatcher found for `#{path}'"
97
89
  end
98
90
 
91
+ # build a response, default values are from the current response.
92
+
99
93
  def build_response body = response.body, status = response.status, head = response.header
100
94
  set_cookie if Global.cookies
101
95
  head.each do |key, value|
@@ -107,6 +101,9 @@ module Ramaze
107
101
  return response
108
102
  end
109
103
 
104
+ # finalizes the session and assigns the key to the response via
105
+ # set_cookie.
106
+
110
107
  def set_cookie
111
108
  session.finalize
112
109
  hash = {:value => session.session_id, :path => '/'}
@@ -10,7 +10,7 @@ module Ramaze
10
10
 
11
11
  # The response is passed to each filter by sending .call(response) to it.
12
12
 
13
- trait :filter => [
13
+ FILTER = [
14
14
  # Ramaze::Tool::Localize,
15
15
  # Ramaze::Tool::Tidy
16
16
  ]
@@ -19,8 +19,7 @@ module Ramaze
19
19
  def process(path)
20
20
  body = Controller.handle(path)
21
21
  response = Dispatcher.build_response(body)
22
- filter = ancestral_trait[:filter]
23
- filter.inject(response){|r,f| f.call(r) }
22
+ FILTER.inject(response){|r,f| f.call(r) }
24
23
  end
25
24
  end
26
25
  end
@@ -4,6 +4,12 @@
4
4
  module Ramaze
5
5
  module Dispatcher
6
6
  class Error
7
+ HANDLE_ERROR = {
8
+ Exception => [ 500, '/error' ],
9
+ Ramaze::Error::NoAction => [ 404, '/error' ],
10
+ Ramaze::Error::NoController => [ 404, '/error' ],
11
+ }
12
+
7
13
  class << self
8
14
  trait :last_error => nil
9
15
 
@@ -11,10 +17,9 @@ module Ramaze
11
17
  log_error(error)
12
18
 
13
19
  Thread.current[:exception] = error
14
- handle_error = Dispatcher.trait[:handle_error]
15
20
 
16
- key = error.class.ancestors.find{|a| handle_error[a]}
17
- status, path = *handle_error[key || Exception]
21
+ key = error.class.ancestors.find{|a| HANDLE_ERROR[a]}
22
+ status, path = *HANDLE_ERROR[key || Exception]
18
23
 
19
24
  unless error.message =~ %r(`#{path.split('/').last}')
20
25
  Response.current.status = status
@@ -11,10 +11,7 @@ module Ramaze
11
11
  end
12
12
 
13
13
  def lookup_paths
14
- [ (BASEDIR/'proto'/'public'),
15
- Global.controllers.map{|c| c.trait[:public]},
16
- './public'
17
- ].flatten.select{|f| ::File.directory?(f.to_s)}.map{|f| ::File.expand_path(f)}
14
+ [ Global.public_proto, Global.public_root ].flatten
18
15
  end
19
16
 
20
17
  def open_file(path)
@@ -5,17 +5,17 @@ module Ramaze
5
5
 
6
6
  # The general Namespace for Ramazes Errorclasses
7
7
 
8
- module Error
8
+ class Error < StandardError
9
9
  # No action found on Controller
10
- class NoAction < StandardError; end
10
+ class NoAction < Error; end
11
11
 
12
12
  # No Controller found for request
13
- class NoController < StandardError; end
13
+ class NoController < Error; end
14
14
 
15
15
  # Wrong parameter count for action
16
- class WrongParameterCount < StandardError; end
16
+ class WrongParameterCount < Error; end
17
17
 
18
18
  # Error while transformation in template
19
- class Template < StandardError; end
19
+ class Template < Error; end
20
20
  end
21
21
  end
@@ -29,6 +29,9 @@ module Ramaze
29
29
  o "Turn on cookies for all requests.",
30
30
  :cookies => true, :cli => true
31
31
 
32
+ o "Compile Templates",
33
+ :compile => false, :cli => false
34
+
32
35
  o "All subclasses of Controller are collected here.",
33
36
  :controllers => Set.new
34
37
 
@@ -51,7 +54,10 @@ module Ramaze
51
54
  :port => 7000, :cli => 7000
52
55
 
53
56
  o "Specify the shadowing public directory (default in proto)",
54
- :public_root => ( BASEDIR / 'proto' / 'public' )
57
+ :public_proto => ( BASEDIR / 'proto' / 'public' )
58
+
59
+ o "Specify the public directory of your application serving static files",
60
+ :public_root => File.expand_path('./public')
55
61
 
56
62
  o "Record all Request objects by assigning a filtering Proc to me.",
57
63
  :record => false
@@ -56,7 +56,7 @@ module Ramaze
56
56
  end
57
57
 
58
58
  def ports
59
- (port..(port + (spawn - 1)))
59
+ (port.to_i..(port.to_i + (spawn.to_i - 1)))
60
60
  end
61
61
 
62
62
  def sourcereload=(interval)
@@ -71,8 +71,6 @@ module Ramaze
71
71
  keys.map{|key| __send__(key)}
72
72
  end
73
73
 
74
- private # Internal helpers
75
-
76
74
  def create_member key, value = nil
77
75
  Inform.warn "Create #{key}=#{value.inspect} on Global"
78
76
 
@@ -56,19 +56,17 @@ module Ramaze
56
56
  meths = instance_methods(false)
57
57
  wrap(*meths, &block)
58
58
  end
59
+ end
59
60
 
60
- def before_process(action)
61
- block = ancestral_trait[:aspects][:before][action.method]
62
- before = action.controller.instance_eval(&block) if block
63
- before
61
+ class Action
62
+ def before_process
63
+ block = controller.ancestral_trait[:aspects][:before][method]
64
+ instance.instance_eval(&block) if block
64
65
  end
65
66
 
66
- def after_process(action)
67
- block = ancestral_trait[:aspects][:after][action.method]
68
- after = action.controller.instance_eval(&block) if block
69
- after
67
+ def after_process
68
+ block = controller.ancestral_trait[:aspects][:after][method]
69
+ instance.instance_eval(&block) if block
70
70
  end
71
-
72
- module_function :before_process, :after_process
73
71
  end
74
72
  end