ramaze 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. data/Rakefile +1 -1
  2. data/doc/AUTHORS +2 -0
  3. data/doc/CHANGELOG +173 -0
  4. data/doc/changes.txt +4184 -0
  5. data/doc/changes.xml +4186 -0
  6. data/doc/meta/announcement.txt +22 -25
  7. data/doc/meta/internals.txt +146 -9
  8. data/examples/blog/template/index.xhtml +5 -2
  9. data/examples/fcgi.rb +13 -0
  10. data/examples/wiktacular/main.rb +8 -0
  11. data/examples/wiktacular/mkd/link/2007-07-20_19-45-51.mkd +1 -0
  12. data/examples/wiktacular/mkd/link/current.mkd +1 -0
  13. data/examples/wiktacular/mkd/main/2007-07-20_16-31-33.mkd +1 -0
  14. data/examples/wiktacular/mkd/main/2007-07-20_19-21-12.mkd +1 -0
  15. data/examples/wiktacular/mkd/main/2007-07-20_19-23-10.mkd +2 -0
  16. data/examples/wiktacular/mkd/main/2007-07-20_19-45-07.mkd +2 -0
  17. data/examples/wiktacular/mkd/main/current.mkd +2 -0
  18. data/examples/wiktacular/mkd/markdown/current.mkd +3 -0
  19. data/examples/wiktacular/mkd/testing/2007-07-20_16-43-46.mkd +2 -0
  20. data/examples/wiktacular/mkd/testing/2007-07-20_19-43-50.mkd +3 -0
  21. data/examples/wiktacular/mkd/testing/2007-07-21_18-46-01.mkd +11 -0
  22. data/examples/wiktacular/mkd/testing/2007-07-21_18-46-32.mkd +13 -0
  23. data/examples/wiktacular/mkd/testing/2007-07-21_18-47-08.mkd +17 -0
  24. data/examples/wiktacular/mkd/testing/2007-07-21_18-47-54.mkd +17 -0
  25. data/examples/wiktacular/mkd/testing/current.mkd +17 -0
  26. data/examples/wiktacular/public/favicon.ico +0 -0
  27. data/examples/wiktacular/public/screen.css +72 -0
  28. data/examples/wiktacular/src/controller.rb +44 -0
  29. data/examples/wiktacular/src/model.rb +92 -0
  30. data/examples/wiktacular/src/page.rb +66 -0
  31. data/examples/wiktacular/template/edit.xhtml +7 -0
  32. data/examples/wiktacular/template/index.xhtml +11 -0
  33. data/examples/wiktacular/template/new.xhtml +7 -0
  34. data/lib/proto/main.rb +2 -0
  35. data/lib/proto/public/error.zmr +3 -0
  36. data/lib/proto/public/js/jquery.js +1755 -1334
  37. data/lib/proto/template/index.xhtml +2 -2
  38. data/lib/ramaze.rb +8 -3
  39. data/lib/ramaze/action/render.rb +11 -0
  40. data/lib/ramaze/adapter/base.rb +11 -7
  41. data/lib/ramaze/cache.rb +25 -10
  42. data/lib/ramaze/cache/memcached.rb +16 -1
  43. data/lib/ramaze/cache/yaml_store.rb +10 -0
  44. data/lib/ramaze/controller.rb +12 -2
  45. data/lib/ramaze/controller/error.rb +9 -3
  46. data/lib/ramaze/controller/resolve.rb +20 -18
  47. data/lib/ramaze/dispatcher.rb +13 -4
  48. data/lib/ramaze/dispatcher/action.rb +7 -3
  49. data/lib/ramaze/dispatcher/error.rb +24 -2
  50. data/lib/ramaze/dispatcher/file.rb +12 -6
  51. data/lib/ramaze/global.rb +0 -3
  52. data/lib/ramaze/global/dsl.rb +9 -0
  53. data/lib/ramaze/global/globalstruct.rb +7 -1
  54. data/lib/ramaze/helper/aspect.rb +4 -2
  55. data/lib/ramaze/helper/cgi.rb +2 -2
  56. data/lib/ramaze/helper/file.rb +3 -0
  57. data/lib/ramaze/helper/link.rb +20 -0
  58. data/lib/ramaze/helper/markaby.rb +3 -0
  59. data/lib/ramaze/helper/pager.rb +10 -17
  60. data/lib/ramaze/helper/partial.rb +9 -3
  61. data/lib/ramaze/inform/analogger.rb +14 -0
  62. data/lib/ramaze/inform/growl.rb +7 -0
  63. data/lib/ramaze/inform/hub.rb +9 -0
  64. data/lib/ramaze/inform/informer.rb +9 -3
  65. data/lib/ramaze/inform/informing.rb +9 -3
  66. data/lib/ramaze/inform/knotify.rb +5 -1
  67. data/lib/ramaze/inform/syslog.rb +3 -0
  68. data/lib/ramaze/inform/xosd.rb +12 -0
  69. data/lib/ramaze/template.rb +3 -0
  70. data/lib/ramaze/template/amrita2.rb +2 -0
  71. data/lib/ramaze/template/erubis.rb +1 -0
  72. data/lib/ramaze/template/ezamar.rb +1 -0
  73. data/lib/ramaze/template/ezamar/element.rb +17 -11
  74. data/lib/ramaze/template/ezamar/engine.rb +5 -0
  75. data/lib/ramaze/template/ezamar/render_partial.rb +4 -2
  76. data/lib/ramaze/template/haml.rb +4 -0
  77. data/lib/ramaze/template/liquid.rb +4 -0
  78. data/lib/ramaze/template/markaby.rb +4 -0
  79. data/lib/ramaze/template/remarkably.rb +4 -0
  80. data/lib/ramaze/tool.rb +10 -0
  81. data/lib/ramaze/tool/localize.rb +1 -1
  82. data/lib/ramaze/trinity/session.rb +8 -1
  83. data/lib/ramaze/version.rb +1 -1
  84. data/rake_tasks/maintaince.rake +2 -2
  85. data/spec/ramaze/action/basics.rb +1 -1
  86. data/spec/ramaze/cache.rb +11 -0
  87. data/spec/ramaze/controller.rb +0 -14
  88. data/spec/ramaze/dispatcher/file.rb +5 -5
  89. data/spec/ramaze/dispatcher/public/favicon.ico +0 -0
  90. data/spec/ramaze/dispatcher/public/test_download.css +141 -0
  91. data/spec/ramaze/error.rb +21 -7
  92. data/spec/ramaze/helper/link.rb +15 -0
  93. data/spec/ramaze/helper/pager.rb +26 -3
  94. data/spec/ramaze/helper/partial.rb +2 -2
  95. metadata +43 -4
  96. data/doc/COPYING.ja +0 -51
@@ -7,9 +7,9 @@
7
7
  <ol>
8
8
  <li><code>template/index.xhtml</code>, which this text</li>
9
9
  <li><code>src/elements/page.rb</code>, which is the Element around this text</li>
10
- <li><code>src/controllers/main.rb</code>, where you can change the header of this page and the <a href="/notemplate">notemplate</a> action</li>
10
+ <li><code>src/controllers/main.rb</code>, where you can change the header of this page and the <a href="/notemplate">notemplate</a> action</li>
11
11
  <li><code>src/model.rb</code>, which is the the persistent backend for your app</li>
12
12
  </ol>
13
13
  </p>
14
- <p>You can also read the tutorial in the <code>doc/</code> directory of ramaze or browse the <a href="http://ramaze.rubyforge.org/rdoc/files/doc/README.html">rdocs</a><p>
14
+ <p>You can also read the tutorial in the <code>doc/</code> directory of ramaze or browse the <a href="http://ramaze.rubyforge.org/rdoc/files/doc/README.html">rdocs</a></p>
15
15
  </Page>
data/lib/ramaze.rb CHANGED
@@ -4,6 +4,7 @@
4
4
  # The main namespace for Ramaze
5
5
  module Ramaze
6
6
  BASEDIR = File.dirname(File.expand_path(__FILE__))
7
+ SEEED = $0.dup
7
8
  $:.unshift BASEDIR
8
9
  end
9
10
 
@@ -15,6 +16,7 @@ require 'ramaze/snippets'
15
16
  require 'ramaze/inform'
16
17
  require 'ramaze/global'
17
18
  require 'ramaze/cache'
19
+ require 'ramaze/tool'
18
20
 
19
21
  # Startup
20
22
  require 'ramaze/controller'
@@ -42,10 +44,13 @@ module Ramaze
42
44
  Inform.info("Starting up Ramaze (Version #{VERSION})")
43
45
 
44
46
  starter = caller[0].split(':').first
45
- return unless ($0 == starter or options.delete(:force))
46
47
 
47
- trait[:essentials].each do |obj|
48
- obj.startup(options)
48
+ if $0 == starter or options.delete(:force)
49
+ SEEED.replace(starter)
50
+
51
+ trait[:essentials].each do |obj|
52
+ obj.startup(options)
53
+ end
49
54
  end
50
55
  end
51
56
 
@@ -22,6 +22,11 @@ module Ramaze
22
22
  end
23
23
  end
24
24
 
25
+ # Return the cached output of the action if it exists, otherwise do a
26
+ # normal Action#uncached_render and store the output in the Cache.actions.
27
+ # Action#cached_render is only called if Action#should_cache? returns
28
+ # true.
29
+
25
30
  def cached_render
26
31
  action_cache = Cache.actions
27
32
 
@@ -34,6 +39,9 @@ module Ramaze
34
39
  action_cache[relaxed_hash] = uncached_render
35
40
  end
36
41
 
42
+ # The 'normal' rendering process. Passes the Action instance to
43
+ # Action#engine.transform, which returns the output of the action.
44
+
37
45
  def uncached_render
38
46
  [ before_process,
39
47
  engine.transform(self),
@@ -41,6 +49,9 @@ module Ramaze
41
49
  ].join
42
50
  end
43
51
 
52
+ # return true if the action is flagged for caching. Called by
53
+ # Action#render.
54
+
44
55
  def should_cache?
45
56
  ctrait = controller.trait
46
57
  actions_cached = ctrait[:actions_cached]
@@ -27,22 +27,26 @@ module Ramaze
27
27
  Inform.debug("Stopping #{self.class}")
28
28
  end
29
29
 
30
+ # This is called by Rack with the usual env, subsequently calls
31
+ # ::respond with it.
32
+ #
33
+ # The method itself acts just as a wrapper for benchmarking and then
34
+ # calls .finish on the current response after ::respond has finished.
35
+
30
36
  def call(env)
31
37
  if Ramaze::Global.benchmarking
32
- time = Benchmark.measure{ respond env }
38
+ time = Benchmark.measure{ respond(env) }
33
39
  Inform.debug("request took #{time.real}s")
34
40
  else
35
41
  respond env
36
42
  end
37
43
 
38
- finish
44
+ Thread.current[:response].finish
39
45
  end
40
46
 
41
- def finish
42
- response = Thread.current[:response]
43
-
44
- response.finish
45
- end
47
+ # Initializes Request with env and an empty Response. Records the
48
+ # request into Ramaze::Record if Global.record is true.
49
+ # Then goes on and calls Dispatcher::handle with request and response.
46
50
 
47
51
  def respond env
48
52
  request, response = Request.new(env), Response.new
data/lib/ramaze/cache.rb CHANGED
@@ -14,18 +14,29 @@ module Ramaze
14
14
  include Enumerable
15
15
  CACHES = {} unless defined?(CACHES)
16
16
 
17
+ attr_accessor :cache
18
+
17
19
  class << self
18
20
 
21
+ # Initializes the Cache for the general caches Ramaze uses.
22
+ # Cache#startup is called by Ramaze#startup, when initializing the
23
+ # Ramaze.trait(:essentials).
24
+
19
25
  def startup(options)
20
26
  Cache.add :compiled, :actions, :patterns, :resolved, :shield
21
27
  end
22
28
 
23
29
  # This will define a method to access a new cache directly over
24
- # sinleton-methods on Cache
30
+ # singleton-methods on Cache.
31
+ #---
32
+ # The @cache_name is internally used for caches which do not save
33
+ # different caches in different namespaces, for example memcached.
34
+ #+++
25
35
 
26
36
  def add *keys
27
37
  keys.each do |key|
28
38
  CACHES[key] = new
39
+ CACHES[key].instance_variable_set("@cache_name", key)
29
40
  self.class.class_eval do
30
41
  define_method(key){ CACHES[key] }
31
42
  end
@@ -35,30 +46,34 @@ module Ramaze
35
46
 
36
47
  end
37
48
 
49
+ # Initializes the cache, defined by Global.cache
50
+
38
51
  def initialize(cache = Global.cache)
39
52
  @cache = cache.new
40
53
  end
41
54
 
42
55
  def [](key)
43
- @cache[key.to_s]
56
+ @cache["#{@cache_name}:#{key}"]
44
57
  end
45
58
 
46
59
  def []=(key, value)
47
- @cache[key.to_s] = value
60
+ @cache["#{@cache_name}:#{key}"] = value
48
61
  end
49
62
 
63
+ # deletes the keys of each argument passed from Cache instance.
64
+
50
65
  def delete(*args)
51
66
  args.each do |arg|
52
- @cache.delete(arg.to_s)
67
+ @cache.delete("#{@cache_name}:#{arg}")
53
68
  end
54
69
  end
55
70
 
56
- def method_missing(meth, *args, &block)
57
- if @cache.respond_to?(meth)
58
- @cache.send(meth, *args, &block)
59
- else
60
- super
61
- end
71
+ def clear
72
+ @cache.clear
73
+ end
74
+
75
+ def values_at(*args)
76
+ @cache.values_at(*args.map {|key| "#{@cache_name}:#{key}" })
62
77
  end
63
78
  end
64
79
  end
@@ -3,6 +3,10 @@
3
3
  require 'memcache'
4
4
 
5
5
  module Ramaze
6
+
7
+ # Cache based on the memcache library which utilizes the memcache-daemon to
8
+ # store key/value pairs in namespaces.
9
+
6
10
  class MemcachedCache
7
11
 
8
12
  # Create a new MemcachedCache with host, port and a namespace that defaults
@@ -10,7 +14,8 @@ module Ramaze
10
14
  #
11
15
  # For your own usage you should use another namespace.
12
16
 
13
- def initialize(host = 'localhost', port = '11211', namespace = 'ramaze')
17
+ def initialize(host = 'localhost', port = '11211', namespace = SEEED)
18
+ namespace = Digest::SHA1.hexdigest(namespace)[0..16]
14
19
  @cache = MemCache.new("#{host}:#{port}", :namespace => namespace, :multithread => true)
15
20
  end
16
21
 
@@ -63,6 +68,10 @@ end
63
68
  # add the MemCache#clear method
64
69
 
65
70
  class MemCache
71
+
72
+ # MemCache.clear sends 'flush_all' command to all registered MemCache
73
+ # servers.
74
+
66
75
  def clear
67
76
  raise MemCacheError, "Update of readonly cache" if @readonly
68
77
 
@@ -71,7 +80,13 @@ class MemCache
71
80
  end
72
81
  end
73
82
 
83
+ # implements the flushing of MemCache server. Flushes a single server,
84
+ # MemCache#clear can be used for clearing out all MemCache servers.
85
+
74
86
  class Server
87
+
88
+ # Serverside implementation of the #clear functionality for MemCache
89
+
75
90
  def flush_all
76
91
  socket.write "flush_all\r\n"
77
92
  end
@@ -3,6 +3,10 @@
3
3
  require 'yaml/store'
4
4
 
5
5
  module Ramaze
6
+
7
+ # Cache based on _whys YAML::Store, which uses PStore to serialize objects
8
+ # as YAML in a thread-safe manner.
9
+
6
10
  class YAMLStoreCache
7
11
 
8
12
  attr_accessor :file
@@ -23,16 +27,22 @@ module Ramaze
23
27
  end
24
28
  end
25
29
 
30
+ # Loads @file into memory via YAML::load_file
31
+
26
32
  def underlying_yaml
27
33
  YAML.load_file(@file)
28
34
  end
29
35
 
36
+ # clears the YAML::Store based cache, by emptying the YAML file.
37
+
30
38
  def clear
31
39
  transaction do |y|
32
40
  File.open(@file, 'w+'){|f| f.puts({}.to_yaml)}
33
41
  end
34
42
  end
35
43
 
44
+ # Deletes the key from YAML::Store based cache.
45
+
36
46
  def delete(key)
37
47
  transaction do |y|
38
48
  y.delete(key)
@@ -60,7 +60,11 @@ module Ramaze
60
60
  end
61
61
  end
62
62
 
63
- Inform.debug("mapped Controllers: #{Global.mapping.inspect}")
63
+ if Global.mapping.empty?
64
+ Inform.warn("No Controllers mapped, will serve /public only.")
65
+ else
66
+ Inform.debug("mapped Controllers: #{Global.mapping.inspect}")
67
+ end
64
68
  end
65
69
 
66
70
  # checks paths for existance and logs a warning if it doesn't exist yet.
@@ -70,7 +74,7 @@ module Ramaze
70
74
  end
71
75
 
72
76
  # 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
77
+ # this will build a new default mapping-point, MainController is put
74
78
  # at '/' by default.
75
79
 
76
80
  def mapping
@@ -90,6 +94,12 @@ module Ramaze
90
94
  end
91
95
  end
92
96
 
97
+ # Returns the Controller at a mapped path.
98
+
99
+ def at(mapping)
100
+ Global.mapping[mapping.to_s]
101
+ end
102
+
93
103
  # Define a template_root for Controller, returns the current template_root
94
104
  # if no argument is given.
95
105
  # Runs every given path through Controller::check_path
@@ -8,14 +8,20 @@ module Ramaze
8
8
  #
9
9
  # Error-pages can be in whatever the templating-engine of your controller
10
10
  # is set to.
11
- # Thread.current[:exception]
11
+ # Ramaze::Dispatcher::Error.current
12
12
  # holds the exception thrown.
13
13
 
14
14
  def error
15
- error = Thread.current[:exception]
16
- @backtrace = error.backtrace[0..20]
15
+ error = Ramaze::Dispatcher::Error.current
17
16
  title = error.message
18
17
 
18
+ unless Action.current.template
19
+ response['Content-Type'] = 'text/plain'
20
+ return [title, "", error.backtrace].flatten.join("\n")
21
+ end
22
+
23
+ @backtrace = error.backtrace[0..20]
24
+
19
25
  @colors = []
20
26
  min = 200
21
27
  max = 255
@@ -14,7 +14,12 @@ module Ramaze
14
14
 
15
15
  def resolve(path)
16
16
  if found = Cache.resolved[path]
17
- return found
17
+ if found.respond_to?(:relaxed_hash)
18
+ return found
19
+ else
20
+ Inform.warn("Found faulty `#{path}' in Cache.resolved, deleting it for sanity.")
21
+ Cache.resolved.delete path
22
+ end
18
23
  end
19
24
 
20
25
  mapping = Global.mapping
@@ -32,7 +37,7 @@ module Ramaze
32
37
  action = controller.resolve_action(method, *params)
33
38
  template = action.template
34
39
 
35
- valid_action = (action.method or (params.empty? && action.template))
40
+ valid_action = (action.method or (params.empty? && template))
36
41
 
37
42
  return Cache.resolved[path] = action if valid_action
38
43
  end
@@ -75,7 +80,7 @@ module Ramaze
75
80
 
76
81
  def template_paths
77
82
  @template_root ||= Global.template_root / Global.mapping.invert[self]
78
- [ @template_root, Global.public_root, Global.public_proto ].compact
83
+ [ @template_root, Global.public_root ].compact
79
84
  end
80
85
 
81
86
  def resolve_method(name, *params)
@@ -100,28 +105,24 @@ module Ramaze
100
105
  def pattern_for(path)
101
106
  atoms = path.split('/').grep(/\S/)
102
107
  atoms.unshift('')
103
- patterns, joiners = [], ['/']
108
+ patterns, joiner = [], '/'
104
109
 
105
110
  atoms.size.times do |enum|
106
111
  enum += 1
107
- joiners << '__' if enum == 3
108
-
109
- joiners.each do |joinus|
110
- pattern = atoms.dup
112
+ pattern = atoms.dup
111
113
 
112
- controller = pattern[0, enum].join(joinus)
113
- controller.gsub!(/^__/, '/')
114
- controller = "/" if controller == ""
114
+ controller = pattern[0, enum].join(joiner)
115
+ controller.gsub!(/^__/, '/')
116
+ controller = "/" if controller == ""
115
117
 
116
- pattern = pattern[enum..-1]
117
- args, temp = [], []
118
+ pattern = pattern[enum..-1]
119
+ args, temp = [], []
118
120
 
119
- patterns << [controller, 'index', atoms[enum..-1]]
121
+ patterns << [controller, 'index', atoms[enum..-1]]
120
122
 
121
- until pattern.empty?
122
- args << pattern.shift
123
- patterns << [controller, args.join( '__' ), pattern.dup]
124
- end
123
+ until pattern.empty?
124
+ args << pattern.shift
125
+ patterns << [controller, args.join( '__' ), pattern.dup]
125
126
  end
126
127
  end
127
128
 
@@ -145,6 +146,7 @@ module Ramaze
145
146
  # Raises Ramaze::Error::NoAction
146
147
 
147
148
  def raise_no_action(controller, path)
149
+ Thread.current[:failed_controller] = controller
148
150
  raise Ramaze::Error::NoAction, "No Action found for `#{path}' on #{controller}"
149
151
  end
150
152
  end
@@ -12,6 +12,10 @@ require 'ramaze/dispatcher/error'
12
12
  require 'ramaze/dispatcher/file'
13
13
 
14
14
  module Ramaze
15
+
16
+ # The Dispatcher receives requests from adapters and sets up the proper environment
17
+ # to process them and respond.
18
+
15
19
  module Dispatcher
16
20
 
17
21
  # requests are passed to every
@@ -35,7 +39,7 @@ module Ramaze
35
39
  dispatch(path)
36
40
  end
37
41
  rescue Object => error
38
- Dispatcher::Error.process(error)
42
+ Dispatcher::Error.process(error, :path => path, :request => request)
39
43
  end
40
44
 
41
45
  def dispatch(path)
@@ -78,14 +82,19 @@ module Ramaze
78
82
 
79
83
  # Calls .process(path) on every class in Dispatcher::FILTER until one
80
84
  # returns something else than false/nil.
81
- # Raises NoAction otherwise.
82
85
 
83
86
  def filter path
87
+ result = nil
84
88
  FILTER.each do |dispatcher|
85
89
  result = dispatcher.process(path)
86
- return result if result
90
+ return result if result and not result.respond_to?(:exception)
87
91
  end
88
- raise Ramaze::Error::NoAction, "No Dispatcher found for `#{path}'"
92
+
93
+ meta = {
94
+ :path => path,
95
+ :controller => Thread.current[:failed_controller]
96
+ }
97
+ Dispatcher::Error.process(result, meta)
89
98
  end
90
99
 
91
100
  # build a response, default values are from the current response.