ramaze 2008.11 → 2009.01

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 (110) hide show
  1. data/README.markdown +7 -7
  2. data/benchmark/run.rb +1 -1
  3. data/doc/CHANGELOG +662 -0
  4. data/examples/app/blog/model/entry.rb +8 -1
  5. data/examples/app/blog/spec/blog.rb +2 -2
  6. data/examples/app/rapaste/spec/rapaste.rb +1 -1
  7. data/examples/app/rapaste/start.rb +2 -2
  8. data/examples/app/rapaste/view/view.xhtml +3 -0
  9. data/examples/app/todolist/spec/todolist.rb +1 -1
  10. data/examples/app/whywiki/spec/whywiki.rb +1 -1
  11. data/examples/app/wikore/spec/wikore.rb +1 -1
  12. data/examples/app/wikore/src/model.rb +8 -2
  13. data/examples/app/wiktacular/spec/wiktacular.rb +1 -1
  14. data/examples/app/wiktacular/src/model.rb +1 -1
  15. data/examples/basic/partial.rb +28 -0
  16. data/examples/helpers/httpdigest.rb +68 -10
  17. data/examples/misc/ramaise.rb +2 -2
  18. data/examples/templates/template_amrita2.rb +1 -1
  19. data/examples/templates/template_erubis.rb +1 -1
  20. data/examples/templates/template_ezamar.rb +1 -1
  21. data/examples/templates/template_haml.rb +2 -2
  22. data/examples/templates/template_liquid.rb +1 -1
  23. data/examples/templates/template_markaby.rb +2 -2
  24. data/examples/templates/template_nagoro.rb +1 -1
  25. data/examples/templates/template_redcloth.rb +1 -1
  26. data/examples/templates/template_remarkably.rb +2 -2
  27. data/examples/templates/template_tenjin.rb +1 -1
  28. data/examples/templates/template_xslt.rb +1 -1
  29. data/lib/proto/controller/init.rb +2 -1
  30. data/lib/proto/model/init.rb +3 -3
  31. data/lib/proto/public/dispatch.fcgi +2 -2
  32. data/lib/proto/spec/main.rb +3 -3
  33. data/lib/proto/start.rb +4 -0
  34. data/lib/ramaze.rb +6 -0
  35. data/lib/ramaze/action.rb +7 -1
  36. data/lib/ramaze/action/render.rb +6 -5
  37. data/lib/ramaze/cache.rb +1 -0
  38. data/lib/ramaze/cache/file.rb +71 -0
  39. data/lib/ramaze/contrib.rb +1 -1
  40. data/lib/ramaze/contrib/email.rb +2 -0
  41. data/lib/ramaze/contrib/facebook.rb +2 -2
  42. data/lib/ramaze/contrib/file_cache.rb +2 -64
  43. data/lib/ramaze/contrib/sequel/image.rb +1 -1
  44. data/lib/ramaze/controller.rb +9 -1
  45. data/lib/ramaze/controller/resolve.rb +10 -5
  46. data/lib/ramaze/current/request.rb +87 -70
  47. data/lib/ramaze/current/session.rb +3 -5
  48. data/lib/ramaze/current/session/hash.rb +7 -11
  49. data/lib/ramaze/dispatcher/action.rb +2 -0
  50. data/lib/ramaze/dispatcher/file.rb +6 -1
  51. data/lib/ramaze/helper.rb +12 -4
  52. data/lib/ramaze/helper/aspect.rb +2 -2
  53. data/lib/ramaze/helper/bench.rb +43 -0
  54. data/lib/ramaze/helper/form.rb +5 -2
  55. data/lib/ramaze/helper/formatting.rb +4 -0
  56. data/lib/ramaze/helper/gravatar.rb +18 -1
  57. data/lib/ramaze/helper/httpdigest.rb +55 -28
  58. data/lib/ramaze/helper/markaby.rb +1 -1
  59. data/lib/ramaze/helper/maruku.rb +2 -0
  60. data/lib/ramaze/helper/paginate.rb +1 -1
  61. data/lib/ramaze/helper/partial.rb +1 -1
  62. data/lib/ramaze/helper/redirect.rb +22 -4
  63. data/lib/ramaze/helper/user.rb +4 -4
  64. data/lib/ramaze/option.rb +1 -1
  65. data/lib/ramaze/option/holder.rb +3 -3
  66. data/lib/ramaze/reloader.rb +25 -41
  67. data/lib/ramaze/reloader/watch_inotify.rb +85 -0
  68. data/lib/ramaze/reloader/watch_stat.rb +58 -0
  69. data/lib/ramaze/snippets/divide.rb +2 -0
  70. data/lib/ramaze/snippets/numeric/time.rb +1 -1
  71. data/lib/ramaze/snippets/object/__dir__.rb +3 -3
  72. data/lib/ramaze/snippets/object/acquire.rb +3 -6
  73. data/lib/ramaze/snippets/ramaze/acquire.rb +31 -0
  74. data/lib/ramaze/snippets/ramaze/deprecated.rb +2 -1
  75. data/lib/ramaze/spec/helper/mock_http.rb +6 -5
  76. data/lib/ramaze/template/ezamar/render_partial.rb +8 -0
  77. data/lib/ramaze/tool/mime.rb +1 -1
  78. data/lib/ramaze/tool/project_creator.rb +2 -1
  79. data/lib/ramaze/version.rb +2 -2
  80. data/rake_tasks/coverage.rake +4 -5
  81. data/rake_tasks/spec.rake +6 -6
  82. data/ramaze-2008.11.gem +0 -0
  83. data/ramaze.gemspec +759 -758
  84. data/spec/contrib/profiling.rb +2 -2
  85. data/spec/ramaze/action/file_cache.rb +1 -1
  86. data/spec/ramaze/action/layout.rb +1 -1
  87. data/spec/ramaze/controller/actionless_templates.rb +1 -1
  88. data/spec/ramaze/controller/resolve.rb +1 -1
  89. data/spec/ramaze/controller/template_resolving.rb +1 -1
  90. data/spec/ramaze/dispatcher/directory.rb +3 -3
  91. data/spec/ramaze/helper/aspect.rb +1 -1
  92. data/spec/ramaze/helper/partial.rb +1 -1
  93. data/spec/ramaze/localize.rb +1 -1
  94. data/spec/ramaze/rewrite.rb +1 -1
  95. data/spec/ramaze/template.rb +3 -3
  96. data/spec/ramaze/template/amrita2.rb +1 -1
  97. data/spec/ramaze/template/erubis.rb +1 -1
  98. data/spec/ramaze/template/ezamar.rb +1 -1
  99. data/spec/ramaze/template/haml.rb +2 -2
  100. data/spec/ramaze/template/nagoro.rb +1 -1
  101. data/spec/ramaze/template/redcloth.rb +1 -1
  102. data/spec/ramaze/template/sass.rb +1 -1
  103. data/spec/ramaze/template/tenjin.rb +1 -1
  104. data/spec/snippets/object/__dir__.rb +6 -0
  105. data/spec/snippets/{object → ramaze}/acquire.rb +24 -18
  106. metadata +18 -16
  107. data/lib/ramaze/contrib/auto_params.rb +0 -135
  108. data/lib/ramaze/contrib/auto_params/get_args.rb +0 -58
  109. data/spec/contrib/auto_params.rb +0 -121
  110. data/spec/snippets/divide.rb +0 -19
@@ -8,10 +8,10 @@ module Ramaze
8
8
  #
9
9
  # class MainController < Ramaze::Controller
10
10
  # def index
11
- # if user?
12
- # A('login', :href => Rs(:login))
13
- # else
11
+ # if logged_in?
14
12
  # "Hello #{user.name}"
13
+ # else
14
+ # A('login', :href => Rs(:login))
15
15
  # end
16
16
  # end
17
17
  #
@@ -77,7 +77,7 @@ module Ramaze
77
77
  elsif _model.respond_to?(:authenticate)
78
78
  _model.authenticate(creds)
79
79
  else
80
- Log.warn("Helper::User has no callback and %p doesn't respond to #authenticate" % _model)
80
+ Log.warn("Helper::User has no callback and there is no %p::authenticate" % _model)
81
81
  nil
82
82
  end
83
83
  end
@@ -78,7 +78,7 @@ module Ramaze
78
78
  o "Turn on customized error pages. Use Rack::ShowException otherwise.",
79
79
  :error_page, true, :cli => true
80
80
 
81
- o "Caching actions to the filesystem in Global.public_root",
81
+ o "Cache actions to filesystem, uses String as directory name or Global.public_root if other truism",
82
82
  :file_cache, false, :cli => false
83
83
 
84
84
  o "Specify what IP Ramaze will respond to - 0.0.0.0 for all",
@@ -78,7 +78,7 @@ module Ramaze
78
78
  # currently set one.
79
79
  def public_root
80
80
  [ @public_root,
81
- root/@public_root
81
+ File.join(root, @public_root)
82
82
  ].find{|path| File.directory?(path) } || @public_root
83
83
  end
84
84
 
@@ -90,8 +90,8 @@ module Ramaze
90
90
  # the currently set one.
91
91
  def view_root
92
92
  [ @view_root,
93
- root/@view_root,
94
- root/'template',
93
+ File.join(root, @view_root),
94
+ File.join(root, 'template'),
95
95
  ].find{|path| File.directory?(path) } || @view_root
96
96
  end
97
97
 
@@ -11,9 +11,7 @@ module Ramaze
11
11
  # Reloader::Hooks module or include your own module to override the hooks.
12
12
  # You also might have to set the Log constant.
13
13
  #
14
- # What makes it especially suited for use in a production environment is that
15
- # any file will only be checked once and there will only be made one system
16
- # call stat(2).
14
+ # Currently, it uses RInotify if available and falls back to using File.stat.
17
15
  #
18
16
  # Please note that this will not reload files in the background, it does so
19
17
  # only when actively called
@@ -47,11 +45,21 @@ module Ramaze
47
45
  :control => nil, # lambda{ cycle },
48
46
  }
49
47
 
48
+ begin
49
+ gem 'RInotify', '>=0.9' # is older version ok?
50
+ require 'rinotify'
51
+ require 'ramaze/reloader/watch_inotify'
52
+ Watcher = WatchInotify
53
+ rescue LoadError
54
+ # stat always available
55
+ require 'ramaze/reloader/watch_stat'
56
+ Watcher = WatchStat
57
+ end
58
+
50
59
  def initialize(app)
51
60
  @app = app
52
- @last = Time.now
53
- @mtimes = {}
54
- @cache = {}
61
+ @files = {}
62
+ @watcher = Watcher.new
55
63
  options_reload
56
64
  end
57
65
 
@@ -63,7 +71,7 @@ module Ramaze
63
71
  def call(env)
64
72
  options_reload
65
73
 
66
- if @cooldown and Time.now > @last + @cooldown
74
+ @watcher.call(@cooldown) do
67
75
  if @control
68
76
  instance_eval(&@control)
69
77
  elsif @thread
@@ -71,8 +79,6 @@ module Ramaze
71
79
  else
72
80
  cycle
73
81
  end
74
-
75
- @last = Time.now
76
82
  end
77
83
 
78
84
  @app.call(env)
@@ -81,16 +87,8 @@ module Ramaze
81
87
  def cycle
82
88
  before_cycle
83
89
 
84
- rotation do |file, stat|
85
- if mtime = stat.mtime
86
- if mtime > (@mtimes[file] ||= mtime)
87
- safe_load(file)
88
- @mtimes[file] = mtime
89
- end
90
- else
91
- @cache.delete(file)
92
- end
93
- end
90
+ rotation{|file| @watcher.watch(file) }
91
+ @watcher.changed_files{|f| safe_load(f) }
94
92
 
95
93
  after_cycle
96
94
  end
@@ -111,37 +109,23 @@ module Ramaze
111
109
 
112
110
  files.each do |file|
113
111
  next if file =~ @ignore
114
- path, stat = figure_path(file, paths)
115
-
116
- if path and stat
117
- @cache[file] = path
118
- yield(path, stat)
119
- else
120
- # Quite harmless, we just couldn't figure out path for #{file}
112
+ if not @files.has_key?(file) and path = figure_path(file, paths)
113
+ @files[file] = path
114
+ yield path
121
115
  end
122
116
  end
123
117
  end
124
118
 
125
119
  def figure_path(file, paths)
126
- if cached = @cache[file]
127
- stat = File.stat(cached)
128
- return cached, stat if stat.file?
129
- elsif Pathname.new(file).absolute?
130
- stat = File.stat(file)
131
- return file, stat if stat.file? # do directories really end up in $" ?
120
+ if Pathname.new(file).absolute?
121
+ return File.exist?(file) ? file : nil
132
122
  end
133
123
 
134
124
  paths.each do |possible_path|
135
- path = File.join(possible_path, file)
136
-
137
- begin
138
- stat = File.stat(path)
139
- return path, stat if stat.file?
140
- rescue Errno::ENOENT, Errno::ENOTDIR
141
- end
125
+ full_path = File.join(possible_path, file)
126
+ return full_path if File.exist?(full_path)
142
127
  end
143
-
144
- return nil
128
+ nil
145
129
  end
146
130
 
147
131
 
@@ -0,0 +1,85 @@
1
+ module Ramaze
2
+ class Reloader
3
+ # TODO:
4
+ # * There seems to be a problem somewhere that I couldn't identify yet, a
5
+ # file has to be modified twice initially to make it show up as
6
+ # modified here, subsequent changes work just fine.
7
+ # The only workaround I could find right now would be to read/write
8
+ # every single file, but that would be unexpected, irresponsible, and
9
+ # error-prone.
10
+ #
11
+ # NOTE:
12
+ # * I have changed from using a Mutex to using a Queue, which uses a
13
+ # Mutex internally.
14
+
15
+ class WatchInotify
16
+ POLL_INTERVAL = 2 # seconds
17
+ NOTIFY_MASK = RInotify::MODIFY | RInotify::IN_ONESHOT
18
+
19
+ def initialize
20
+ @watcher = RInotify.new
21
+ @changed = Queue.new
22
+ @watcher_thread = start_watcher
23
+ end
24
+
25
+ def call(cooldown)
26
+ yield
27
+ end
28
+
29
+ # TODO: define a finalizer to cleanup? -- reloader never calls #close
30
+
31
+ def start_watcher
32
+ Thread.new{ loop{ watcher_cycle }}
33
+ end
34
+
35
+ # Not much work here, we just have to empty the event queue and push the
36
+ # descriptors for reloading on next request.
37
+ def watcher_cycle
38
+ return unless @watcher.wait_for_events(POLL_INTERVAL)
39
+
40
+ @watcher.each_event do |event|
41
+ @changed.push(event.watch_descriptor)
42
+ end
43
+ end
44
+
45
+ def watch(file)
46
+ return if @watcher.watch_descriptors.has_value?(file)
47
+ return unless File.exist?(file)
48
+
49
+ @watcher.add_watch(file, NOTIFY_MASK)
50
+ rescue Errno::ENOENT
51
+ retry
52
+ end
53
+
54
+ # FIXME:
55
+ # Seems like this won't work due to some bug in the rinotify library.
56
+ # Would be cool if someone could make a FFI version.
57
+
58
+ def remove_watch(file)
59
+ @watcher.rm_watch(file)
60
+ end
61
+
62
+ def close
63
+ @watcher_thread.terminate
64
+ @watcher.close
65
+ true
66
+ end
67
+
68
+ # NOTE:
69
+ # We have to add the changed file again after we got a notification, I
70
+ # have no idea why, but using IN_ONESHOT should make sure that there is
71
+ # no memory leak in the C level even if we add a file again.
72
+ # There is a memory leak however in the watch_descriptors hash, since
73
+ # rinotify won't synchronize the contents properly and will only add to
74
+ # the hash, so we have to clean up ourselves.
75
+ def changed_files
76
+ until @changed.empty?
77
+ descriptor = @changed.shift
78
+ file = @watcher.watch_descriptors.delete(descriptor)
79
+ watch(file)
80
+ yield(file)
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,58 @@
1
+ module Ramaze
2
+ class Reloader
3
+ class WatchStat
4
+ def initialize
5
+ # @files[file_path] = stat
6
+ @files = {}
7
+ @last = Time.now
8
+ end
9
+
10
+ def call(cooldown)
11
+ if cooldown and Time.now > @last + cooldown
12
+ yield
13
+ @last = Time.now
14
+ end
15
+ end
16
+
17
+ # start watching a file for changes
18
+ # true if succeeded, false if failure
19
+ def watch(file)
20
+ return true if watching?(file) # if already watching
21
+ if stat = safe_stat(file)
22
+ @files[file] = stat
23
+ end
24
+ end
25
+
26
+ def watching?(file)
27
+ @files.has_key?(file)
28
+ end
29
+
30
+ # stop watching a file for changes
31
+ def remove_watch(file)
32
+ @files.delete(file)
33
+ end
34
+
35
+ # no need for cleanup
36
+ def close
37
+ end
38
+
39
+ # return files changed since last call
40
+ def changed_files
41
+ @files.each do |file, stat|
42
+ if new_stat = safe_stat(file)
43
+ if new_stat.mtime > stat.mtime
44
+ @files[file] = new_stat
45
+ yield(file)
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ def safe_stat(file)
52
+ File.stat(file)
53
+ rescue Errno::ENOENT, Errno::ENOTDIR
54
+ nil
55
+ end
56
+ end
57
+ end
58
+ end
@@ -6,6 +6,7 @@ class String
6
6
  # Usage:
7
7
  # 'a' / 'b' # => 'a/b'
8
8
  def / obj
9
+ Ramaze.deprecated('String#/', 'File::join')
9
10
  File.join(self, obj.to_s)
10
11
  end
11
12
  end
@@ -15,6 +16,7 @@ class Symbol
15
16
  # Usage:
16
17
  # :dir/:file # => 'dir/file'
17
18
  def / obj
19
+ Ramaze.deprecated('Symbol#/', 'File::join(sym.to_s)')
18
20
  self.to_s / obj
19
21
  end
20
22
  end
@@ -41,7 +41,7 @@ module Ramaze
41
41
 
42
42
  # 365.25 days in a year
43
43
  def years
44
- self * 883612800
44
+ self * 31557600
45
45
  end
46
46
  alias year years
47
47
 
@@ -16,11 +16,11 @@ module Ramaze
16
16
  # This method is convenience for the
17
17
  # File.expand_path(File.dirname(__FILE__))
18
18
  # idiom.
19
- #
20
19
 
21
- def __DIR__()
20
+ def __DIR__(*args)
22
21
  filename = caller[0][/^(.*):/, 1]
23
- File.expand_path(File.dirname(filename))
22
+ dir = File.expand_path(File.dirname(filename))
23
+ ::File.expand_path(::File.join(dir, *args.map{|a| a.to_s}))
24
24
  end
25
25
  end
26
26
  end
@@ -27,12 +27,9 @@ module Ramaze
27
27
  # # require 'src/foo.rb' and 'src/bar.so' and 'src/foobar/baz.rb'
28
28
  # acquire 'src/*', 'src/foobar/*'
29
29
 
30
- def acquire *globs
31
- globs.flatten.each do |glob|
32
- Dir[glob].each do |file|
33
- require file if file =~ /\.(rb|so)$/
34
- end
35
- end
30
+ def acquire(*globs)
31
+ Ramaze.deprecated('Object#acquire', 'Ramaze::acquire')
32
+ Ramaze.acquire(*globs)
36
33
  end
37
34
  end
38
35
 
@@ -0,0 +1,31 @@
1
+ # Copyright (c) 2008 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
+ # Require all .rb and .so files on the given globs, utilizes Dir::[].
6
+ #
7
+ # Examples:
8
+ # # Given following directory structure:
9
+ # # src/foo.rb
10
+ # # src/bar.so
11
+ # # src/foo.yaml
12
+ # # src/foobar/baz.rb
13
+ # # src/foobar/README
14
+ #
15
+ # # requires all files in 'src':
16
+ # Ramaze.acquire 'src/*'
17
+ #
18
+ # # requires all files in 'src' recursive:
19
+ # Ramaze.acquire 'src/**/*'
20
+ #
21
+ # # require 'src/foo.rb' and 'src/bar.so' and 'src/foobar/baz.rb'
22
+ # Ramaze.acquire 'src/*', 'src/foobar/*'
23
+
24
+ def self.acquire(*globs)
25
+ globs.flatten.each do |glob|
26
+ Dir[glob].each do |file|
27
+ require file if file =~ /\.(rb|so)$/
28
+ end
29
+ end
30
+ end
31
+ end
@@ -6,7 +6,8 @@ module Ramaze
6
6
  def self.deprecated(from, to = nil)
7
7
  message = "%s is deprecated"
8
8
  message << ", use %s instead" unless to.nil?
9
- Log.warn(message % [from, to])
9
+ message << " - from: %p"
10
+ Log.warn(message % [from, to, caller[1]])
10
11
  end
11
12
 
12
13
  def self.const_missing(name)
@@ -42,8 +42,9 @@ module MockHTTP
42
42
 
43
43
  def process_request(path, query)
44
44
  options = {}
45
- FISHING.each{|key, value|
46
- options[value] = query.delete(key)} if query.is_a?(Hash)
45
+ FISHING.each do |key, value|
46
+ options[value] = query.delete(key) if query.key?(key)
47
+ end if query.is_a?(Hash)
47
48
  [create_url(path, query), options]
48
49
  end
49
50
 
@@ -54,10 +55,10 @@ module MockHTTP
54
55
  uri.to_s
55
56
  end
56
57
 
57
- def make_query query
58
- return query unless query and not query.is_a?(String)
58
+ def make_query query
59
+ return query unless query and not query.is_a?(String)
59
60
  query.map{|key, value|
60
61
  "#{Rack::Utils.escape(key)}=#{Rack::Utils.escape(value)}"
61
62
  }.join('&')
62
- end
63
+ end
63
64
  end
@@ -7,6 +7,14 @@ require 'ramaze/template/ezamar/engine'
7
7
  module Ezamar
8
8
 
9
9
  # A transformer for <render /> tags.
10
+ #
11
+ # Setup:
12
+ #
13
+ # pipeline = Ramaze::Template::Ezamar::TRANSFORM_PIPELINE
14
+ # pipeline.put_after(::Ezamar::Element, ::Ezamar::RenderPartial)
15
+ # pipline.uniq!
16
+ #
17
+ # See /examples/basic/partial.rb for usage.
10
18
 
11
19
  class RenderPartial
12
20
  extend Ramaze::Helper::Partial