ramaze 0.1.2 → 0.1.3

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.
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.