ramaze 2008.11 → 2009.01

Sign up to get free protection for your applications and to get access to all the features.
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