ramaze 2008.06 → 2008.11

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 (184) hide show
  1. data/README.markdown +6 -6
  2. data/Rakefile +33 -3
  3. data/bin/ramaze +18 -0
  4. data/doc/CHANGELOG +960 -0
  5. data/doc/LEGAL +5 -1
  6. data/doc/meta/announcement.txt +20 -36
  7. data/doc/tutorial/todolist.html +421 -313
  8. data/doc/tutorial/todolist.mkd +33 -16
  9. data/examples/app/blog/spec/blog.rb +3 -3
  10. data/examples/app/rapaste/controller/paste.rb +8 -1
  11. data/examples/app/rapaste/model/paste.rb +3 -0
  12. data/examples/app/rapaste/spec/rapaste.rb +3 -1
  13. data/examples/app/rapaste/start.rb +3 -2
  14. data/examples/app/sourceview/public/sourceview.js +2 -2
  15. data/examples/app/todolist/spec/todolist.rb +6 -6
  16. data/examples/app/todolist/template/index.xhtml +1 -1
  17. data/examples/app/whywiki/spec/whywiki.rb +2 -2
  18. data/examples/app/wikore/spec/wikore.rb +2 -2
  19. data/examples/app/wikore/src/model.rb +4 -3
  20. data/examples/app/wiktacular/spec/wiktacular.rb +7 -7
  21. data/examples/basic/simple.rb +2 -2
  22. data/examples/helpers/paginate.rb +71 -0
  23. data/examples/misc/simple_auth.rb +20 -8
  24. data/lib/proto/controller/init.rb +10 -0
  25. data/lib/proto/controller/main.rb +1 -3
  26. data/lib/proto/model/init.rb +4 -0
  27. data/lib/proto/public/dispatch.fcgi +1 -1
  28. data/lib/proto/spec/main.rb +2 -1
  29. data/lib/proto/start.rb +3 -3
  30. data/lib/proto/start.ru +1 -1
  31. data/lib/proto/view/error.xhtml +4 -4
  32. data/lib/ramaze.rb +8 -3
  33. data/lib/ramaze/action.rb +6 -6
  34. data/lib/ramaze/adapter.rb +1 -6
  35. data/lib/ramaze/adapter/base.rb +30 -27
  36. data/lib/ramaze/adapter/cgi.rb +1 -0
  37. data/lib/ramaze/cache.rb +1 -3
  38. data/lib/ramaze/cache/memcached.rb +3 -5
  39. data/lib/ramaze/contrib/auto_params.rb +2 -2
  40. data/lib/ramaze/contrib/auto_params/get_args.rb +2 -1
  41. data/lib/ramaze/contrib/gems.rb +17 -18
  42. data/lib/ramaze/contrib/gzip_filter.rb +22 -9
  43. data/lib/ramaze/contrib/maruku_uv.rb +59 -0
  44. data/lib/ramaze/contrib/profiling.rb +1 -1
  45. data/lib/ramaze/contrib/rest.rb +16 -13
  46. data/lib/ramaze/contrib/sequel/create_join.rb +25 -0
  47. data/lib/ramaze/contrib/sequel/form_field.rb +129 -0
  48. data/lib/ramaze/contrib/sequel/image.rb +198 -0
  49. data/lib/ramaze/contrib/sequel/relation.rb +82 -0
  50. data/lib/ramaze/controller.rb +33 -34
  51. data/lib/ramaze/controller/resolve.rb +29 -9
  52. data/lib/ramaze/current.rb +60 -20
  53. data/lib/ramaze/current/request.rb +8 -7
  54. data/lib/ramaze/current/response.rb +15 -3
  55. data/lib/ramaze/current/session/flash.rb +8 -0
  56. data/lib/ramaze/dispatcher.rb +17 -9
  57. data/lib/ramaze/dispatcher/action.rb +4 -5
  58. data/lib/ramaze/dispatcher/directory.rb +1 -1
  59. data/lib/ramaze/dispatcher/error.rb +4 -4
  60. data/lib/ramaze/dispatcher/file.rb +4 -4
  61. data/lib/ramaze/gestalt.rb +15 -20
  62. data/lib/ramaze/helper/cgi.rb +7 -15
  63. data/lib/ramaze/helper/formatting.rb +41 -1
  64. data/lib/ramaze/helper/httpdigest.rb +20 -7
  65. data/lib/ramaze/helper/link.rb +4 -6
  66. data/lib/ramaze/helper/paginate.rb +233 -0
  67. data/lib/ramaze/helper/redirect.rb +1 -1
  68. data/lib/ramaze/helper/rest.rb +1 -1
  69. data/lib/ramaze/helper/thread.rb +17 -0
  70. data/lib/ramaze/helper/ultraviolet.rb +44 -0
  71. data/lib/ramaze/helper/user.rb +4 -9
  72. data/lib/ramaze/log.rb +2 -2
  73. data/lib/ramaze/log/analogger.rb +21 -23
  74. data/lib/ramaze/log/growl.rb +21 -23
  75. data/lib/ramaze/log/hub.rb +1 -1
  76. data/lib/ramaze/log/informer.rb +97 -99
  77. data/lib/ramaze/log/knotify.rb +14 -16
  78. data/lib/ramaze/log/logger.rb +11 -13
  79. data/lib/ramaze/log/logging.rb +61 -63
  80. data/lib/ramaze/log/rotatinginformer.rb +168 -0
  81. data/lib/ramaze/log/syslog.rb +41 -31
  82. data/lib/ramaze/log/xosd.rb +70 -72
  83. data/lib/ramaze/option.rb +9 -6
  84. data/lib/ramaze/option/holder.rb +5 -27
  85. data/lib/ramaze/reloader.rb +186 -0
  86. data/lib/ramaze/setup.rb +1 -1
  87. data/lib/ramaze/snippets.rb +13 -0
  88. data/lib/ramaze/snippets/array/put_within.rb +31 -24
  89. data/lib/ramaze/snippets/binding/locals.rb +23 -11
  90. data/lib/ramaze/snippets/dictionary.rb +2 -2
  91. data/lib/ramaze/snippets/fiber.rb +63 -0
  92. data/lib/ramaze/snippets/kernel/constant.rb +36 -21
  93. data/lib/ramaze/snippets/kernel/pretty_inspect.rb +12 -6
  94. data/lib/ramaze/snippets/numeric/filesize_format.rb +24 -17
  95. data/lib/ramaze/snippets/numeric/time.rb +63 -0
  96. data/lib/ramaze/snippets/object/__dir__.rb +29 -0
  97. data/lib/ramaze/snippets/object/acquire.rb +40 -0
  98. data/lib/ramaze/snippets/object/instance_variable_defined.rb +16 -5
  99. data/lib/ramaze/snippets/object/pretty.rb +14 -4
  100. data/lib/ramaze/snippets/object/scope.rb +14 -7
  101. data/lib/ramaze/snippets/ordered_set.rb +25 -14
  102. data/lib/ramaze/snippets/proc/locals.rb +17 -9
  103. data/lib/ramaze/snippets/ramaze/deprecated.rb +13 -0
  104. data/lib/ramaze/snippets/ramaze/fiber.rb +24 -0
  105. data/lib/ramaze/snippets/ramaze/state.rb +86 -0
  106. data/lib/ramaze/snippets/ramaze/struct.rb +45 -0
  107. data/lib/ramaze/snippets/string/camel_case.rb +13 -8
  108. data/lib/ramaze/snippets/string/color.rb +24 -20
  109. data/lib/ramaze/snippets/string/each.rb +14 -3
  110. data/lib/ramaze/snippets/string/end_with.rb +20 -0
  111. data/lib/ramaze/snippets/string/esc.rb +26 -21
  112. data/lib/ramaze/snippets/string/ord.rb +12 -6
  113. data/lib/ramaze/snippets/string/snake_case.rb +13 -7
  114. data/lib/ramaze/snippets/string/start_with.rb +16 -5
  115. data/lib/ramaze/snippets/string/unindent.rb +23 -15
  116. data/lib/ramaze/snippets/thread/into.rb +3 -3
  117. data/lib/ramaze/spec/helper/bacon.rb +5 -5
  118. data/lib/ramaze/spec/helper/mock_http.rb +1 -1
  119. data/lib/ramaze/spec/helper/pretty_output.rb +2 -2
  120. data/lib/ramaze/spec/helper/snippets.rb +8 -0
  121. data/lib/ramaze/template.rb +4 -1
  122. data/lib/ramaze/template/ezamar/textpow.syntax +34 -0
  123. data/lib/ramaze/template/maruku.rb +34 -0
  124. data/lib/ramaze/template/tagz.rb +2 -2
  125. data/lib/ramaze/template/xslt.rb +2 -2
  126. data/lib/ramaze/tool/create.rb +27 -53
  127. data/lib/ramaze/tool/localize.rb +8 -4
  128. data/lib/ramaze/tool/mime.rb +11 -1
  129. data/lib/ramaze/tool/project_creator.rb +110 -0
  130. data/lib/ramaze/trinity.rb +4 -1
  131. data/lib/ramaze/version.rb +1 -1
  132. data/lib/vendor/bacon.rb +323 -0
  133. data/rake_tasks/gem.rake +10 -1
  134. data/rake_tasks/maintenance.rake +40 -2
  135. data/rake_tasks/metric.rake +24 -0
  136. data/rake_tasks/release.rake +17 -4
  137. data/rake_tasks/spec.rake +1 -2
  138. data/ramaze.gemspec +549 -495
  139. data/spec/contrib/auto_params.rb +3 -3
  140. data/spec/contrib/profiling.rb +2 -2
  141. data/spec/examples/simple_auth.rb +2 -2
  142. data/spec/examples/templates/template_haml.rb +0 -2
  143. data/spec/ramaze/action/file_cache.rb +22 -0
  144. data/spec/ramaze/adapter.rb +2 -2
  145. data/spec/ramaze/controller/actionless_templates.rb +1 -1
  146. data/spec/ramaze/controller/subclass.rb +15 -0
  147. data/spec/ramaze/controller/template_resolving.rb +1 -1
  148. data/spec/ramaze/controller/view/bar.xhtml +1 -0
  149. data/spec/ramaze/controller/view/base/another.xhtml +1 -0
  150. data/spec/ramaze/current/session.rb +1 -1
  151. data/spec/ramaze/dispatcher/file.rb +2 -2
  152. data/spec/ramaze/helper/aspect.rb +26 -17
  153. data/spec/ramaze/helper/formatting.rb +13 -0
  154. data/spec/ramaze/log/informer.rb +10 -10
  155. data/spec/ramaze/log/syslog.rb +67 -4
  156. data/spec/ramaze/rewrite.rb +1 -1
  157. data/spec/ramaze/route.rb +1 -1
  158. data/spec/ramaze/struct.rb +47 -0
  159. data/spec/ramaze/template/markaby.rb +1 -1
  160. data/spec/ramaze/template/tagz.rb +1 -1
  161. data/spec/snippets/binding/locals.rb +9 -0
  162. data/spec/snippets/numeric/time.rb +12 -0
  163. data/spec/snippets/{kernel → object}/__dir__.rb +0 -0
  164. data/spec/snippets/{kernel → object}/acquire.rb +0 -0
  165. metadata +90 -81
  166. data/cache.yaml +0 -7
  167. data/examples/app/rammit/spec/rammit.rb +0 -31
  168. data/examples/app/rammit/src/controller/main.rb +0 -3
  169. data/examples/app/rammit/src/controller/page.rb +0 -16
  170. data/examples/app/rammit/src/model.rb +0 -33
  171. data/examples/app/rammit/start.rb +0 -8
  172. data/examples/app/rammit/template/index.xhtml +0 -14
  173. data/examples/app/rammit/template/page/view.xhtml +0 -4
  174. data/lib/ramaze/snippets/kernel/__dir__.rb +0 -23
  175. data/lib/ramaze/snippets/kernel/acquire.rb +0 -34
  176. data/lib/ramaze/snippets/object/thread_accessor.rb +0 -5
  177. data/lib/ramaze/snippets/ramaze/thread_accessor.rb +0 -58
  178. data/lib/ramaze/snippets/struct/fill.rb +0 -23
  179. data/lib/ramaze/snippets/struct/values_at.rb +0 -39
  180. data/lib/ramaze/snippets/symbol/to_proc.rb +0 -24
  181. data/lib/ramaze/sourcereload.rb +0 -176
  182. data/spec/snippets/struct/fill.rb +0 -26
  183. data/spec/snippets/struct/values_at.rb +0 -52
  184. data/spec/snippets/symbol/to_proc.rb +0 -13
data/cache.yaml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- bar:foobar:
3
- :value: bar
4
- :expires:
5
- foo:foobar:
6
- :value: foo
7
- :expires:
@@ -1,31 +0,0 @@
1
- require 'ramaze'
2
- require 'ramaze/spec/helper'
3
-
4
- $LOAD_PATH.unshift base = __DIR__/'..'
5
- spec_require 'hpricot', 'sequel'
6
-
7
- require 'start'
8
-
9
- describe 'Rammit' do
10
- behaves_like 'http'
11
- base = File.expand_path(__DIR__/'..')
12
- ramaze :view_root => base/'template',
13
- :public_root => base/'public'
14
-
15
- it 'should have intro page' do
16
- got = get('/')
17
- doc = Hpricot(got.body)
18
- form = doc.at(:form)
19
- form.at('textarea[@name=text]').should.not == nil
20
- form.at('input[@type=submit @value="Create a site"]').should.not == nil
21
- end
22
-
23
- it 'should create page from intro page' do
24
- got = post('/page/create', 'text' => 'Some text')
25
- refer = got.headers['Location']
26
- refer.should.not == nil
27
- got = get(refer)
28
- doc = Hpricot(got.body)
29
- doc.at('div#text').inner_html.should =~ /Some text/
30
- end
31
- end
@@ -1,3 +0,0 @@
1
- class MainController < Ramaze::Controller
2
- map '/'
3
- end
@@ -1,16 +0,0 @@
1
- class PageController < Ramaze::Controller
2
- map '/page'
3
-
4
- def create
5
- redirect_referrer unless request.post?
6
- if text = request[:text]
7
- page = Page.create :text => text
8
- redirect page.url
9
- end
10
- end
11
-
12
- def view(oid)
13
- page = Page[oid]
14
- @text = page.text
15
- end
16
- end
@@ -1,33 +0,0 @@
1
- require 'sequel'
2
-
3
- DB = Sequel.sqlite
4
-
5
- class User < Sequel::Model(:user)
6
- set_schema do
7
- primary_key :id
8
-
9
- text :nick
10
- text :password
11
- text :email
12
- time :created
13
- end
14
- end
15
-
16
- class Page < Sequel::Model(:page)
17
- include Ramaze::Helper::Link
18
-
19
- set_schema do
20
- primary_key :id
21
-
22
- text :text
23
- end
24
-
25
- def url
26
- R(PageController, :view, id)
27
- end
28
-
29
- end
30
-
31
- [ User, Page ].each do |model|
32
- model.create_table! unless model.table_exists?
33
- end
@@ -1,8 +0,0 @@
1
- require 'rubygems'
2
- require 'ramaze'
3
-
4
- require 'src/model'
5
- require 'src/controller/main'
6
- require 'src/controller/page'
7
-
8
- Ramaze.start
@@ -1,14 +0,0 @@
1
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
- <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
4
- <head>
5
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6
- <title>Rammit</title>
7
- </head>
8
- <body>
9
- <form method="POST" action="#{R PageController, :create}">
10
- <textarea name="text"></textarea>
11
- <input type="submit" value="Create a site" />
12
- </form>
13
- </body>
14
- </html>
@@ -1,4 +0,0 @@
1
- <div id="text">
2
- #@text
3
- </div>
4
-
@@ -1,23 +0,0 @@
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
- # Extensions for Kernel
5
-
6
- module Kernel
7
- unless defined?__DIR__
8
-
9
- # This is similar to +__FILE__+ and +__LINE__+, and returns a String
10
- # representing the directory of the current file is.
11
- # Unlike +__FILE__+ the path returned is absolute.
12
- #
13
- # This method is convenience for the
14
- # File.expand_path(File.dirname(__FILE__))
15
- # idiom.
16
- #
17
-
18
- def __DIR__()
19
- filename = caller[0][/^(.*):/, 1]
20
- File.expand_path(File.dirname(filename))
21
- end
22
- end
23
- end
@@ -1,34 +0,0 @@
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
- # Extensions for Kernel
5
-
6
- module Kernel
7
-
8
- # Require all .rb and .so files on the given globs, utilizes Dir::[].
9
- #
10
- # Examples:
11
- # # Given following directory structure:
12
- # # src/foo.rb
13
- # # src/bar.so
14
- # # src/foo.yaml
15
- # # src/foobar/baz.rb
16
- # # src/foobar/README
17
- #
18
- # # requires all files in 'src':
19
- # acquire 'src/*'
20
- #
21
- # # requires all files in 'src' recursive:
22
- # acquire 'src/**/*'
23
- #
24
- # # require 'src/foo.rb' and 'src/bar.so' and 'src/foobar/baz.rb'
25
- # acquire 'src/*', 'src/foobar/*'
26
-
27
- def acquire *globs
28
- globs.flatten.each do |glob|
29
- Dir[glob].each do |file|
30
- require file if file =~ /\.(rb|so)$/
31
- end
32
- end
33
- end
34
- end
@@ -1,5 +0,0 @@
1
- require(File.expand_path(File.join(File.dirname(__FILE__), '../ramaze/thread_accessor')))
2
-
3
- class Object
4
- include Ramaze::ThreadAccessor
5
- end
@@ -1,58 +0,0 @@
1
- module Ramaze
2
-
3
- # A alike of attr_accessor and friends, but for thread variables in
4
- # Thread::current
5
- module ThreadAccessor
6
-
7
- # Iterate over the names and yield accordingly.
8
- # names are either objects responding to #to_sym or hashes.
9
- #
10
- # It's only used within this module for abstractin-purposes.
11
- # Usage below.
12
- def self.each(*names)
13
- names.each do |name|
14
- if name.respond_to?(:to_hash)
15
- name.to_hash.each do |key, meth|
16
- key, meth = key.to_sym, meth.to_sym
17
- yield key, meth
18
- end
19
- else
20
- key = meth = name.to_sym
21
- yield key, meth
22
- end
23
- end
24
- end
25
-
26
- # thread_writer and thread_reader, initializer is a block that may be given
27
- # and its result will be the new value in case the reader was never called
28
- # before or the value wasn't set before.
29
- def thread_accessor(*names, &initializer)
30
- thread_writer(*names)
31
- thread_reader(*names, &initializer)
32
- end
33
-
34
- # Simple writer accessor to Thread::current[key]=
35
- def thread_writer(*names)
36
- ThreadAccessor.each(*names) do |key, meth|
37
- define_method("#{meth}="){|obj| Thread.current[key] = obj }
38
- end
39
- end
40
-
41
- # Reader accessor for Thread::current[key]
42
- def thread_reader(*names, &initializer)
43
- ThreadAccessor.each(*names) do |key, meth|
44
- if initializer
45
- define_method(meth) do
46
- unless Thread.current.key?(key)
47
- Thread.current[key] = instance_eval(&initializer)
48
- else
49
- Thread.current[key]
50
- end
51
- end
52
- else
53
- define_method(meth){ Thread.current[key] }
54
- end
55
- end
56
- end
57
- end
58
- end
@@ -1,23 +0,0 @@
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
- # Extensions for Struct
5
-
6
- class Struct
7
-
8
- # Action = Struct.new('Action', :template, :method, :params)
9
- #
10
- # a = Action.fill(:template => nil, :method => :meth, :params => [1])
11
- # # => #<struct Struct::Action template=nil, method=:meth, params=[1]>
12
-
13
- def self.fill(hash = {})
14
- instance = new
15
- to_s = members.first.respond_to?(:to_str)
16
- hash.each do |key, value|
17
- key = to_s ? key.to_s : key.to_sym
18
- next unless members.include?(key)
19
- instance.send("#{key}=", value)
20
- end
21
- instance
22
- end
23
- end
@@ -1,39 +0,0 @@
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
- # Extensions for Struct
5
-
6
- class Struct
7
- undef values_at
8
-
9
- # Example:
10
- # Point = Struct.new(:x, :y)
11
- # point = Point.new(15, 10)
12
- # point.values_at(:y, :x)
13
- # # => [10, 15]
14
- # point.values_at(0, 1)
15
- # # => [15, 10]
16
- # point.values_at(0..1)
17
- # # => [15, 10]
18
-
19
- def values_at(*keys)
20
- if keys.all?{|key| key.respond_to?(:to_int) and not key.is_a?(Symbol) }
21
- keys.map{|key| values[key.to_int] }
22
- else
23
- out = []
24
-
25
- keys.each do |key|
26
- case key
27
- when Range
28
- key.each do |r|
29
- out << self[r]
30
- end
31
- else
32
- out << self[key]
33
- end
34
- end
35
-
36
- out
37
- end
38
- end
39
- end
@@ -1,24 +0,0 @@
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
- # Extensions for Symbol
5
-
6
- class Symbol
7
- unless method_defined?(:to_proc)
8
-
9
- # Turns the symbol into a simple proc, which is especially useful for enumerations. Examples:
10
- #
11
- # # The same as people.collect { |p| p.name }
12
- # people.collect(&:name)
13
- #
14
- # # The same as people.select { |p| p.manager? }.collect { |p| p.salary }
15
- # people.select(&:manager?).collect(&:salary)
16
- #
17
- # [1, 2, 3].map(&:to_s) # => ['1', '2', '3']
18
- # %w[a b c].map(&:to_sym) # => [:a, :b, :c]
19
-
20
- def to_proc
21
- Proc.new{|*args| args.shift.__send__(self, *args) }
22
- end
23
- end
24
- end
@@ -1,176 +0,0 @@
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
-
6
- # SourceReload provides a way to reload changed files automatically during
7
- # runtime. Its default behaviour in Ramaze is to check periodically for
8
- # files with newer mtime and then attempts to load them in a controlled
9
- # manner.
10
-
11
- class SourceReload
12
-
13
- # Called from Ramaze::startup, just assigns a new instance to
14
- # Global.sourcreloader
15
- def self.startup(options = {})
16
- Thread.main[:sourcereload] = new
17
- end
18
-
19
- def self.restart
20
- Log.dev("Restart SourceReload")
21
- shutdown
22
- startup
23
- end
24
-
25
- # Maybe make this better?
26
- def self.shutdown
27
- new(false)
28
- end
29
-
30
- attr_reader :thread
31
- attr_accessor :interval
32
-
33
- # Setup the @mtimes hash. any new file will be assigned it's last modified
34
- # time (mtime) so we don't reload a file when we see it the first time.
35
- #
36
- # The thread only runs if Global.sourcereload is set.
37
- def initialize(interval = Global.sourcereload)
38
- if sr = Thread.main[:sourcereload]
39
- sr.interval = interval
40
- else
41
- @interval = interval
42
- startup
43
- end
44
- end
45
-
46
- def startup
47
- return unless @interval
48
- Log.dev("Startup SourceReload")
49
-
50
- @mtimes = Hash.new{|h,k| h[k] = mtime(k) }
51
-
52
- @thread = Thread.new{
53
- current = Thread.current
54
- current.priority = -1
55
-
56
- while iv = @interval
57
- rotate
58
- sleep iv
59
- end
60
- }
61
- end
62
-
63
- # One iteration of rotate will look for files that changed since the last
64
- # iteration and will try to #safe_load it.
65
- # This method is quite handy if you want direct control over when your
66
- # code is reloaded.
67
- #
68
- # Usage example:
69
- #
70
- # trap :HUP do
71
- # Ramaze::Log.info "reloading source"
72
- # Thread.main[:sourcereload].rotate
73
- # end
74
- #
75
-
76
- def rotate
77
- before_rotation
78
-
79
- rotation do |file|
80
- mtime = mtime(file)
81
-
82
- if mtime > @mtimes[file]
83
- safe_load(file)
84
- end
85
- end
86
-
87
- after_rotation
88
- end
89
-
90
- # Iterates over the $LOADED_FEATURES ($") and $LOAD_PATH ($:) and tries to
91
- # find either absolute paths or tries to find one by combining paths and files.
92
- # Every found file is yielded to the rotate method.
93
-
94
- def rotation
95
- files = Array[$0, *$LOADED_FEATURES].uniq
96
- paths = Array['./', *$LOAD_PATH].uniq
97
-
98
- files.each do |file|
99
- if Pathname.new(file).absolute?
100
- yield(file) if File.file?(file)
101
- else
102
- paths.each do |path|
103
- full = File.join(path, file)
104
- if File.file?(full)
105
- break yield(full)
106
- end
107
- end
108
- end
109
- end
110
- end
111
-
112
- # Safe mtime
113
- def mtime(file)
114
- File.mtime(file)
115
- rescue Errno::ENOENT
116
- false
117
- end
118
-
119
- # A safe Kernel::load, issuing the hooks depending on the results
120
- def safe_load(file)
121
- before_safe_load(file)
122
- load(file)
123
- after_safe_load_succeed(file)
124
- rescue Object => ex
125
- after_safe_load_failed(file, ex)
126
- ensure
127
- @mtimes[file] = mtime(file)
128
- end
129
- end
130
-
131
- # Holds hooks that are called before and after #reload and #safe_load
132
-
133
- module SourceReloadHooks
134
- # Overwrite to add actions before the reload rotation is started.
135
-
136
- def before_rotation
137
- end
138
-
139
- # Overwrite to add actions after the reload rotation has ended.
140
-
141
- def after_rotation
142
- end
143
-
144
- # Overwrite to add actions before a file is Kernel::load-ed
145
-
146
- def before_safe_load(file)
147
- Log.debug("reload #{file}")
148
- end
149
-
150
- # Overwrite to add actions after a file is Kernel::load-ed successfully,
151
- # by default we clean the Cache for compiled templates and resolved actions.
152
-
153
- def after_safe_load_succeed(file)
154
- Cache.compiled.clear
155
- Cache.resolved.clear
156
- Cache.action_methods.clear
157
- after_safe_load(file)
158
- end
159
-
160
- # Overwrite to add custom hook in addition to default Cache cleaning
161
-
162
- def after_safe_load(file)
163
- end
164
-
165
- # Overwrite to add actions after a file is Kernel::load-ed unsuccessfully,
166
- # by default we output an error-message with the exception.
167
-
168
- def after_safe_load_failed(file, error)
169
- Log.error(error)
170
- end
171
- end
172
-
173
- class SourceReload
174
- include SourceReloadHooks
175
- end
176
- end