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
@@ -5,8 +5,17 @@ require 'ramaze/inform/informing'
5
5
  require 'ramaze/inform/hub'
6
6
  require 'ramaze/inform/informer'
7
7
 
8
+ begin
9
+ require 'win32console' if RUBY_PLATFORM =~ /win32/i
10
+ rescue LoadError => ex
11
+ puts ex
12
+ puts "For nice colors on windows, please `gem install win32console`"
13
+ Ramaze::Informer.trait[:colorize] = false
14
+ end
15
+
8
16
  module Ramaze
9
17
  autoload :Analogger, "ramaze/inform/analogger.rb"
18
+ autoload :Knotify, "ramaze/inform/knotify.rb"
10
19
  autoload :Syslog, "ramaze/inform/syslog.rb"
11
20
  autoload :Growl, "ramaze/inform/growl.rb"
12
21
  autoload :Xosd, "ramaze/inform/xosd.rb"
@@ -1,14 +1,18 @@
1
1
  # Copyright (c) 2006 Michael Fellinger m.fellinger@gmail.com
2
2
  # All files in this distribution are subject to the terms of the Ruby license.
3
3
 
4
+ require 'set'
5
+
4
6
  module Ramaze
5
7
  class LogHub
6
8
  include Informing
7
9
 
8
10
  attr_accessor :loggers
11
+ attr_accessor :ignored_tags
9
12
 
10
13
  def initialize(*loggers)
11
14
  @loggers = loggers
15
+ @ignored_tags = Set.new
12
16
  @loggers.map! do |logger|
13
17
  next(nil) if logger == self
14
18
  logger.is_a?(Class) ? logger.new : logger
@@ -18,6 +22,7 @@ module Ramaze
18
22
  end
19
23
 
20
24
  def inform(tag, *args)
25
+ return if @ignored_tags.include?(tag)
21
26
  @loggers.each do |logger|
22
27
  logger.inform(tag, *args)
23
28
  end
@@ -5,7 +5,10 @@ module Ramaze
5
5
  class Informer
6
6
  include Informing
7
7
 
8
- attr_accessor :colorize, :out
8
+ attr_accessor :out, :colorize
9
+
10
+ # Should Ramaze try to use colors?
11
+ trait :colorize => true
9
12
 
10
13
  # parameter for Time.now.strftime
11
14
  trait :timestamp => "%Y-%m-%d %H:%M:%S"
@@ -14,14 +17,16 @@ module Ramaze
14
17
  trait :format => "[%time] %prefix %text"
15
18
 
16
19
  # Which tag should be in what color
17
- trait :colors => {
20
+ COLORS = {
18
21
  :info => :green,
19
22
  :debug => :yellow,
20
23
  :warn => :red,
21
24
  :error => :red,
22
25
  }
23
26
 
24
- def initialize(out = $stdout, colorize = nil)
27
+ def initialize(out = $stdout)
28
+ @colorize = false
29
+
25
30
  @out =
26
31
  case out
27
32
  when STDOUT, :stdout, 'stdout'
@@ -34,12 +39,13 @@ module Ramaze
34
39
  if out.respond_to?(:puts)
35
40
  out
36
41
  else
37
- colorize = false
38
42
  File.open(out.to_s, 'ab+')
39
43
  end
40
44
  end
41
45
 
42
- @colorize = @out.tty? rescue false if colorize.nil?
46
+ if @out.respond_to?(:tty?) and class_trait[:colorize]
47
+ @colorize = @out.tty?
48
+ end
43
49
  end
44
50
 
45
51
  def shutdown
@@ -56,7 +62,7 @@ module Ramaze
56
62
  prefix = tag.to_s.upcase.ljust(5)
57
63
 
58
64
  if @colorize
59
- color = class_trait[:colors][tag] ||= :white
65
+ color = COLORS[tag] ||= :white
60
66
  prefix.replace prefix.send(color)
61
67
  end
62
68
 
@@ -2,6 +2,18 @@
2
2
  # All files in this distribution are subject to the terms of the Ruby license.
3
3
 
4
4
  module Ramaze
5
+
6
+ # This module provides a basic skeleton for your own loggers to be compatible.
7
+ # The minimal usage is like this:
8
+ #
9
+ # class MyLogger
10
+ # include Informing
11
+ #
12
+ # def inform(tag, *args)
13
+ # p tag => args
14
+ # end
15
+ # end
16
+
5
17
  module Informing
6
18
  def tag_inform(tag, meth, *strings)
7
19
  strings.each do |string|
@@ -10,24 +22,33 @@ module Ramaze
10
22
  end
11
23
  end
12
24
 
13
- def info(*strings)
14
- tag_inform(:info, :to_s, *strings)
25
+ # Converts everything given to strings and passes them on with :info
26
+
27
+ def info(*objects)
28
+ tag_inform(:info, :to_s, *objects)
15
29
  end
16
30
 
17
- def warn(*strings)
18
- tag_inform(:warn, :to_s, *strings)
31
+ # Converts everything given to strings and passes them on with :warn
32
+
33
+ def warn(*objects)
34
+ tag_inform(:warn, :to_s, *objects)
19
35
  end
20
36
 
21
- def debug(*strings)
22
- tag_inform(:debug, :inspect, *strings)
37
+ # inspects objects if they are no strings. Tag is :debug
38
+
39
+ def debug(*objects)
40
+ tag_inform(:debug, :inspect, *objects)
23
41
  end
24
42
 
25
43
  alias << debug
26
44
 
45
+ # Takes either an Exception or just a String, formats backtraces to be a bit
46
+ # more readable and passes all of this on to tag_inform :error
47
+
27
48
  def error(ex)
28
49
  if ex.respond_to?(:exception)
29
50
  message = ex.backtrace[0..Global.backtrace_size]
30
- message.map!{|m| m.gsub(/^#{Dir.pwd}/, '.') }
51
+ message.map{|m| m.gsub!(/^#{Dir.pwd}/, '.') }
31
52
  message.unshift(ex.inspect)
32
53
  else
33
54
  message = ex.to_s
@@ -35,10 +56,14 @@ module Ramaze
35
56
  tag_inform(:error, :to_s, *message)
36
57
  end
37
58
 
59
+ # raises
60
+
38
61
  def inform(*args)
39
62
  raise "#inform should be implemented by an instance including this module (#{self})"
40
63
  end
41
64
 
65
+ # nothing
66
+
42
67
  def shutdown
43
68
  end
44
69
 
@@ -0,0 +1,21 @@
1
+ # Copyright (c) 2006 Michael Fellinger m.fellinger@gmail.com
2
+ # All files in this distribution are subject to the terms of the Ruby license.
3
+
4
+ module Ramaze
5
+
6
+ class Knotify
7
+ include Informing
8
+
9
+ trait :present => 16
10
+
11
+ # Please see for more information:
12
+ # http://lukeplant.me.uk/articles.php?id=3
13
+ def inform(tag, *messages)
14
+ present = class_trait[:present]
15
+ tag = tag.to_s.capitalize
16
+ messages.flatten.each do |message|
17
+ system(%{dcop knotify default notify Ramaze "#{tag}" "#{message}" '' '' #{present} 0})
18
+ end
19
+ end
20
+ end
21
+ end
@@ -2,40 +2,74 @@
2
2
  # All files in this distribution are subject to the terms of the Ruby license.
3
3
 
4
4
  require 'xosd'
5
+ require 'thread'
5
6
 
6
7
  module Ramaze
7
8
 
8
9
  class Xosd < ::Xosd
9
- include Informing
10
+ attr_accessor :options
10
11
 
11
- trait :timeout => 3
12
- trait :lines => 3
12
+ include Informing
13
13
 
14
- trait :colors => {
15
- :error => "#FF0000",
16
- :info => "#00FF00",
17
- :warn => "#EAA61E",
18
- :debug => "#FFFFFF"
14
+ DEFAULT = {
15
+ :font_size => 20,
16
+ :font => "-*-*-*-*-*-*-%d-*-*-*-*-*-*-*",
17
+ :align => 'center',
18
+ :color => '#FFFFFF',
19
+ :lines => 3,
20
+ :valign => 'top',
21
+ :timeout => 3,
22
+ :outline_color => "#000000",
23
+ :outline_width => 1,
24
+ :vertical_offset => 20,
25
+ :colors => {
26
+ :error => "#FF0000",
27
+ :info => "#00FF00",
28
+ :warn => "#EAA61E",
29
+ :debug => "#FFFF00"
30
+ },
19
31
  }
20
32
 
21
- def initialize
22
- super(class_trait[:lines])
23
-
24
- self.font = "-*-*-*-*-*-*-24-*-*-*-*-*-*-*"
25
- self.align = 'center'
26
- self.color = '#FFFFFF'
27
- self.valign = 'top'
28
- self.timeout = class_trait[:timeout]
29
- self.outline_color = "#000000"
30
- self.outline_width = 1
31
- self.vertical_offset = 20
32
- end
33
+ # keys to ignore when setting the options to the instance.
34
+ IGNORE = [:colors, :font_size, :lines]
35
+
36
+ # Here new messages are pushed to eventually displaying them.
37
+ QUEUE = Queue.new
38
+
39
+ def initialize(options = {})
40
+ @options = DEFAULT.merge(options)
41
+
42
+ super(@options[:lines])
33
43
 
34
- def inform(tag, *args)
35
- self.color = class_trait[:colors][tag.to_sym]
44
+ @options.each do |key, value|
45
+ next if IGNORE.include?(key)
46
+ value %= @options[:font_size] if key == :font
47
+ send("#{key}=", value)
48
+ end
49
+
50
+ Thread.new(self) do |xosd|
51
+ loop do
52
+ items = []
53
+ lines = xosd.options[:lines]
54
+ items << QUEUE.shift until QUEUE.empty? or items.size >= lines
55
+
56
+ unless items.empty?
57
+ # pad up with empty lines to avoid dragging around old messages.
58
+ items << [:info, ' '] until items.size >= lines
59
+
60
+ items.each_with_index do |(tag, message), i|
61
+ xosd.color = xosd.options[:colors][tag.to_sym]
62
+ xosd.display(message, i)
63
+ end
64
+ end
65
+ sleep xosd.options[:timeout]
66
+ end
67
+ end
68
+ end
36
69
 
37
- args.each_with_index do |arg, i|
38
- display(arg, i)
70
+ def inform(tag, *messages)
71
+ messages.each do |message|
72
+ QUEUE << [tag, message]
39
73
  end
40
74
  end
41
75
  end
@@ -9,7 +9,8 @@ module Ramaze
9
9
 
10
10
  def initialize interval = 1, reload_glob = %r{(^\./)|#{Dir.pwd}|ramaze}
11
11
  @interval, @reload_glob = interval, reload_glob
12
- @mtimes, @map = {}, []
12
+ @map, @files, @paths = [], [], []
13
+ @mtimes = {}
13
14
  end
14
15
 
15
16
  def start
@@ -45,6 +46,7 @@ module Ramaze
45
46
  #
46
47
 
47
48
  def reload
49
+ SourceReloadHooks.before_reload
48
50
  all_reload_files.each do |file|
49
51
  mtime = mtime(file)
50
52
 
@@ -53,6 +55,7 @@ module Ramaze
53
55
  Inform.debug("reload #{file}")
54
56
  @mtimes[file] = mtime if safe_load(file)
55
57
  end
58
+ SourceReloadHooks.after_reload
56
59
  end
57
60
 
58
61
  def all_reload_files
@@ -79,11 +82,37 @@ module Ramaze
79
82
  end
80
83
 
81
84
  def safe_load(file)
85
+ SourceReloadHooks.before_safe_load(file)
82
86
  load(file)
87
+ SourceReloadHooks.after_safe_load_succeed(file)
83
88
  true
84
89
  rescue Object => ex
85
90
  Inform.error(ex)
91
+ SourceReloadHooks.after_safe_load_failed(file, ex)
86
92
  false
87
93
  end
88
94
  end
95
+
96
+ # Holds hooks that are called before and after #reload and #safe_load
97
+
98
+ module SourceReloadHooks
99
+ module_function
100
+
101
+ def before_reload
102
+ end
103
+
104
+ def after_reload
105
+ end
106
+
107
+ def before_safe_load(file)
108
+ end
109
+
110
+ def after_safe_load_succeed(file)
111
+ Cache.compiled.clear
112
+ Cache.resolved.clear
113
+ end
114
+
115
+ def after_safe_load_failed(file, error)
116
+ end
117
+ end
89
118
  end
@@ -7,31 +7,35 @@
7
7
  module Ramaze
8
8
  module Template
9
9
 
10
+ COMPILED = {} unless defined?(COMPILED)
11
+
12
+ # Place register_engine puts the class and extensions for templating engines
13
+
14
+ ENGINES = {} unless defined?(ENGINES)
15
+
10
16
  %w[ Amrita2 Erubis Haml Liquid Markaby Remarkably ].each do |const|
11
17
  autoload(const, "ramaze/template/#{const.downcase}")
12
18
  end
13
19
 
14
- # The superclass for all templates, doesn't do much more than including
15
- # Ramaze::Helper and defining #reaction_or_file
20
+ # The superclass for all templates, contains the shared behaviour of
21
+ # the templates and includes Ramaze::Helper
16
22
 
17
23
  class Template
18
24
  include Ramaze::Helper
19
25
 
20
26
  class << self
21
27
 
22
- # pass it the results of the method of the controller
23
- # and a possible file, it will see if the file is an actual file
28
+ # calls result_and_file with the given action and returns the first of
29
+ # the result of the controller or content of the file.
24
30
 
25
31
  def reaction_or_file action
26
- reaction = render_method(action)
27
-
28
- if file = action.template
29
- File.read(file)
30
- else
31
- reaction.to_s
32
- end
32
+ result_and_file(action).reverse.compact.first
33
33
  end
34
34
 
35
+ # Takes an Action and returns the result from sending the action.method
36
+ # to the controller via render_method and reads the contents of the file
37
+ # if given.
38
+
35
39
  def result_and_file(action)
36
40
  result = render_method(action)
37
41
 
@@ -42,9 +46,26 @@ module Ramaze
42
46
  [result, content]
43
47
  end
44
48
 
49
+ # returns nil if no method is on the action, otherwise it will send the
50
+ # action and optional parameters to the controller via __send__ and
51
+ # return the unaltered result
52
+
45
53
  def render_method(action)
46
54
  return unless method = action.method
47
- action.controller.__send__(method, *action.params)
55
+ action.instance.__send__(method, *action.params)
56
+ end
57
+
58
+ # This is a wrapper to use Global.compile without even thinking about it.
59
+ # Don't use it if your engine is not based on a compile/eval principle.
60
+
61
+ def wrap_compile(action, template = nil)
62
+ template ||= reaction_or_file(action).to_s
63
+
64
+ if Global.compile
65
+ Cache.compiled[action.relaxed_hash] ||= compile(action, template)
66
+ else
67
+ compile(action, template)
68
+ end
48
69
  end
49
70
  end
50
71
  end
@@ -3,32 +3,33 @@
3
3
 
4
4
  require 'amrita2/template'
5
5
 
6
- module Ramaze::Template
6
+ module Ramaze
7
+ module Template
8
+ # Is responsible for compiling a template using the Amrita2 templating engine.
7
9
 
8
- # Is responsible for compiling a template using the Amrita2 templating engine.
10
+ class Amrita2 < Template
9
11
 
10
- class Amrita2 < Template
12
+ ENGINES[self] = %w[ amrita amr ]
11
13
 
12
- Ramaze::Controller.register_engine self, %w[ amrita ]
14
+ class << self
13
15
 
14
- class << self
16
+ # Takes an Action
17
+ # The file is rendered using Amrita2::TemplateFile.
18
+ # The Controller is used as the object for expansion.
19
+ #
20
+ # The parameters are set to @params in the controller before expansion.
15
21
 
16
- # Takes an Action
17
- # The file is rendered using Amrita2::TemplateFile.
18
- # The Controller is used as the object for expansion.
19
- #
20
- # The parameters are set to @params in the controller before expansion.
22
+ def transform action
23
+ instance, params, file =
24
+ action.instance, action.params, action.template
25
+ raise_no_action(action) unless file
21
26
 
22
- def transform action
23
- controller, params, file =
24
- action.controller, action.params, action.template
25
- raise_no_action(action) unless file
26
-
27
- template = ::Amrita2::TemplateFile.new(file)
28
- out = ''
29
- controller.instance_variable_set('@params', params)
30
- template.expand(out, controller)
31
- out
27
+ template = ::Amrita2::TemplateFile.new(file)
28
+ out = ''
29
+ instance.instance_variable_set('@params', params)
30
+ template.expand(out, instance)
31
+ out
32
+ end
32
33
  end
33
34
  end
34
35
  end